Midway ingkey/shopcat

This commit is contained in:
Tim Holloway 2022-01-04 10:17:43 -05:00
parent a86f45e4c4
commit 9a88b81b7a
7 changed files with 126 additions and 93 deletions

View File

@ -3,6 +3,10 @@ package com.mousetech.gourmetj;
import com.mousetech.gourmetj.persistence.model.Ingredient; import com.mousetech.gourmetj.persistence.model.Ingredient;
import com.mousetech.gourmetj.persistence.model.IngredientIF; import com.mousetech.gourmetj.persistence.model.IngredientIF;
import com.mousetech.gourmetj.persistence.model.Recipe; import com.mousetech.gourmetj.persistence.model.Recipe;
import com.mousetech.gourmetj.persistence.model.Shopcat;
import net.bytebuddy.asm.Advice.This;
import com.mousetech.gourmetj.IngredientDigester; import com.mousetech.gourmetj.IngredientDigester;
import com.mousetech.gourmetj.IngredientDigester.IngredientAmountFormat; import com.mousetech.gourmetj.IngredientDigester.IngredientAmountFormat;
@ -355,22 +359,22 @@ public class IngredientUI implements IngredientIF {
ingredient.setUnit(unit); ingredient.setUnit(unit);
} }
// This goes to the shopCats table via ManyToOne at save
// time.
private String shopCat;
/** /**
* @return the shopCat * @return the shopCat
*/ */
public String getShopCat() { public String getShopCat() {
return shopCat; Shopcat scat = this.ingredient.getShopCat();
if ( scat == null ) {
return null;
}
return scat.getShopcategory();
} }
/** /**
* @param shopCat the shopCat to set * @param shopCat the shopCat to set
*/ */
public void setShopCat(String shopCat) { public void setShopCat(Shopcat shopCat) {
this.shopCat = shopCat; this.ingredient.setShopCat(shopCat);
} }
/** /**

View File

@ -62,7 +62,7 @@ public class RecipeDetailBean implements Serializable {
} }
/** /**
* Persistency service for Recipes * Persistency service for Recipes, Shopcats and Categories
*/ */
@Inject @Inject
@ -257,7 +257,7 @@ public class RecipeDetailBean implements Serializable {
if (recipe == null) { if (recipe == null) {
return null; return null;
} }
Set<Category> cList = recipe.getCategories(); Set<Category> cList = recipe.getCategories();
StringBuffer sb = new StringBuffer(35); StringBuffer sb = new StringBuffer(35);
boolean first = true; boolean first = true;
@ -308,7 +308,7 @@ public class RecipeDetailBean implements Serializable {
// Shopcat is an eager fetch on Ingredient // Shopcat is an eager fetch on Ingredient
Shopcat shopCat = ing.getShopCat(); Shopcat shopCat = ing.getShopCat();
if (shopCat != null) { if (shopCat != null) {
ingUi.setShopCat(shopCat.getShopcategory()); ingUi.setShopCat(shopCat);
} }
} }
return list; return list;
@ -510,11 +510,13 @@ public class RecipeDetailBean implements Serializable {
} }
public boolean isMoveUpAble() { public boolean isMoveUpAble() {
if (isSelectionActive()) { return true;
List<IngredientUI> rows = getWrappedIngredients(); // TODO:
return !rows.get(0).isSelected(); // if (isSelectionActive()) {
} // List<IngredientUI> rows = getWrappedIngredients();
return false; // return !rows.get(0).isSelected();
// }
// return false;
} }
public boolean isMoveDownAble() { public boolean isMoveDownAble() {
@ -572,24 +574,6 @@ public class RecipeDetailBean implements Serializable {
return "main"; return "main";
} }
/**
* Apply ingredient group IDs (optional) to individual
* ingredients.
*
* @param wrappedIngredients The wrapped ingredient facade.
*/
private void updateRecipeGroups(
List<IngredientUI> wrappedIngredients) {
String ingGroup = null;
for (IngredientUI ingUI : wrappedIngredients) {
if (ingUI.isIngGroup()) {
ingGroup = ingUI.getItem();
} else {
ingUI.getIngredient().setInggroup(ingGroup);
}
}
}
/** /**
* Update ingredients and shopcat from UI model * Update ingredients and shopcat from UI model
* *
@ -612,34 +596,58 @@ public class RecipeDetailBean implements Serializable {
iList.clear(); iList.clear();
for (IngredientUI iui : saveIng) { for (IngredientUI iui : saveIng) {
Ingredient ing = iui.getIngredient(); Ingredient ing = iui.getIngredient();
ing.setRecipe(recipe); ing.setRecipe(recipe);
String ingKey = iui.getIngkey(); if ( ! updateShopcat(ing) ) {
String shopCatName = iui.getShopCat(); return false;
Shopcat scat = ing.getShopCat();
if (scat == null) {
if ((ingKey != null) && !ingKey.isBlank()) {
scat = new Shopcat();
// scat.setIngkey(ingKey);
scat.setShopcategory(shopCatName);
ing.setShopCat(scat);
} else {
JSFUtils.addErrorMessage(
"Shopping Category requires an Ingredient Key");
return false;
}
} else {
if ((ingKey == null) || ingKey.isBlank()) {
ing.setShopCat(null);
} else {
ing.getShopCat()
.setShopcategory(shopCatName);
}
} }
iList.add(ing); iList.add(ing);
} }
return true; return true;
} }
/**
* Apply ingredient group IDs (optional) to individual
* ingredients.
*
* @param wrappedIngredients The wrapped ingredient facade.
*/
private void updateRecipeGroups(
List<IngredientUI> wrappedIngredients) {
String ingGroup = null;
for (IngredientUI ingUI : wrappedIngredients) {
if (ingUI.isIngGroup()) {
ingGroup = ingUI.getItem();
} else {
ingUI.getIngredient().setInggroup(ingGroup);
}
}
}
/**
* Update shopcat for Ingredient.
*
* @param ing Ingredient to update
* @return true if update succeeded.
*/
private boolean updateShopcat(Ingredient ing) {
final String ingKey = ing.getIngkey();
if ( (ingKey == null) || (ingKey.isBlank())) {
ing.setIngkey(null);
ing.setShopCat(null);
return true;
}
Shopcat scat = recipeService.findShopcatForIngredientKey(ingKey);
if ( scat == null ) {
JSFUtils.addErrorMessage(
"No Shopping Category is defined for Ingredient Key "+ ingKey);
return false;
}
ing.setShopCat(scat);
return true;
}
/** /**
* Parse out the comma-separated category text control and * Parse out the comma-separated category text control and
* post the results as children of the recipe * post the results as children of the recipe
@ -797,8 +805,10 @@ public class RecipeDetailBean implements Serializable {
return shopcatList; return shopcatList;
} }
public void ajaxShopcat(AjaxBehaviorEvent event) { public void ajaxUpdateShopcat(AjaxBehaviorEvent event) {
log.warn("SHOPCAT "); log.warn("SHOPCAT ");
// Shopcat scat = recipeService.findShopcatForIngredientKey(ssss);
// ing.setShopcat(scat);
} }
// *** // ***

View File

@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository;
import com.mousetech.gourmetj.persistence.model.Shopcat; import com.mousetech.gourmetj.persistence.model.Shopcat;
/** /**
* JpaRepository for Shoppind Categories, which relate ManyToOne to Ingredient. * JpaRepository for Shopping Categories, which relate ManyToOne to Ingredient.
* Service method is @see RecipeService * Service method is @see RecipeService
* *
* @author timh * @author timh
@ -27,4 +27,6 @@ public interface ShopcatRepository
@Query(value = SQL_FIND_CATEGORIES, nativeQuery = true) @Query(value = SQL_FIND_CATEGORIES, nativeQuery = true)
public List<String> findDistinctCategoryNative(); public List<String> findDistinctCategoryNative();
public Shopcat findShopcatByIngkey(String ingkey);
} }

View File

@ -20,9 +20,7 @@ public class Ingredient implements Serializable, IngredientIF {
@ManyToOne(fetch = FetchType.EAGER, cascade = { @ManyToOne(fetch = FetchType.EAGER, cascade = {
CascadeType.PERSIST, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REFRESH }, optional = true) CascadeType.REFRESH }, optional = true)
@JoinColumn(name = "ingkey", insertable = false, @JoinColumn(name = "ingkey", referencedColumnName = "ingkey")
updatable = false, nullable = true,
foreignKey = @ForeignKey(name = "ingkey"))
Shopcat shopCat; Shopcat shopCat;
/** /**
@ -53,7 +51,7 @@ public class Ingredient implements Serializable, IngredientIF {
@Column(name = "inggroup") @Column(name = "inggroup")
private String inggroup; private String inggroup;
@Column(name = "ingkey") @Column(name = "ingkey",insertable = false, updatable = false)
private String ingkey; private String ingkey;
@Column(name = "item") @Column(name = "item")

View File

@ -39,7 +39,10 @@ public class Shopcat implements Serializable {
@Column(name = "id") @Column(name = "id")
private Long id; private Long id;
//@Column(name = "ingkey", unique = true, nullable = false ) @Column(name = "ingkey", unique = true, nullable = false )
private String ingkey;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "ingkey" ) @OneToMany(fetch = FetchType.LAZY, mappedBy = "ingkey" )
private List<Ingredient> ingredients; private List<Ingredient> ingredients;
@ -73,7 +76,21 @@ public class Shopcat implements Serializable {
public void setId(Long id) { public void setId(Long id) {
this.id = id; this.id = id;
} }
/**
* @return the ingkey
*/
public String getIngkey() {
return ingkey;
}
/**
* @param ingkey the ingkey to set
*/
public void setIngkey(String ingkey) {
this.ingkey = ingkey;
}
public Integer getPosition() { public Integer getPosition() {
return this.position; return this.position;
} }

View File

@ -7,19 +7,15 @@ import java.util.Optional;
import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedNativeQuery;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import com.mousetech.gourmetj.RecipeDetailBean;
import com.mousetech.gourmetj.persistence.dao.CategoryRepository; import com.mousetech.gourmetj.persistence.dao.CategoryRepository;
import com.mousetech.gourmetj.persistence.dao.IngredientRepository;
import com.mousetech.gourmetj.persistence.dao.RecipeRepository; import com.mousetech.gourmetj.persistence.dao.RecipeRepository;
import com.mousetech.gourmetj.persistence.dao.ShopcatRepository; import com.mousetech.gourmetj.persistence.dao.ShopcatRepository;
import com.mousetech.gourmetj.persistence.model.Category;
import com.mousetech.gourmetj.persistence.model.Ingredient; import com.mousetech.gourmetj.persistence.model.Ingredient;
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;
@ -27,6 +23,17 @@ import com.mousetech.gourmetj.persistence.model.Shopcat;
@Named @Named
@ApplicationScoped @ApplicationScoped
@Transactional @Transactional
/**
* Persistence service class for Recipes.
*
* While normally, I would have separate service classes for
* different Entity Working Sets, Recipes are so central to this
* application, this class contains additional functions that
* would ordinarily have their own Service classes.
*
* @author timh
* @since Jan 4, 2022
*/
public class RecipeService implements Serializable { public class RecipeService implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -54,14 +61,6 @@ public class RecipeService implements Serializable {
return recipeRepository.findDetailsById(recipeId); return recipeRepository.findDetailsById(recipeId);
} }
/**
* final String sql = "SELECT DISTINCT cuisine from recipe" +
* " where cuisine is not null and cuisine <> ''" + " ORDER
* BY cuisine ASC";
*
* @return
*/
public List<String> findCuisines() { public List<String> findCuisines() {
return recipeRepository.FindCuisinesNative(); return recipeRepository.FindCuisinesNative();
} }
@ -72,10 +71,13 @@ public class RecipeService implements Serializable {
} }
public void delete(Recipe recipe) { public void delete(Recipe recipe) {
// TODO Auto-generated method stub recipeRepository.delete(recipe);
} }
/**
* ShopcatService as a sub-function of RecipeService
*/
@Inject @Inject
ShopcatRepository shopcatRepository; ShopcatRepository shopcatRepository;
@ -83,6 +85,14 @@ public class RecipeService implements Serializable {
return shopcatRepository.findDistinctCategoryNative(); return shopcatRepository.findDistinctCategoryNative();
} }
public Shopcat findShopcatForIngredientKey(String ingkey) {
return shopcatRepository.findShopcatByIngkey(ingkey);
}
/**
* CategoryService as a sub-function of RecipeService
*/
@Inject @Inject
CategoryRepository categoryRepository; CategoryRepository categoryRepository;

View File

@ -135,6 +135,7 @@
<f:facet name="header">Ingredients</f:facet> <f:facet name="header">Ingredients</f:facet>
<h:panelGroup id="ingButtons"> <h:panelGroup id="ingButtons">
<p:commandButton value="Up" <p:commandButton value="Up"
disabled="#{not recipeDetailBean.moveUpAble}"
id="ctlUp" id="ctlUp"
> >
<f:ajax <f:ajax
@ -144,6 +145,7 @@
/> />
</p:commandButton> </p:commandButton>
<p:commandButton value="Down" <p:commandButton value="Down"
disabled="#{not recipeDetailBean.moveDownAble}"
id="ctlDown" id="ctlDown"
> >
<f:ajax <f:ajax
@ -193,9 +195,10 @@
id="selected" id="selected"
value="#{item.selected}" value="#{item.selected}"
> >
<!-- <f:ajax immediate="true" <f:ajax
render="ingredientTable" immediate="true"
/> --> render="pnlIngredients"
/>
</p:selectBooleanCheckbox> </p:selectBooleanCheckbox>
</p:column> </p:column>
<p:column <p:column
@ -260,22 +263,11 @@
<f:facet name="header"> <f:facet name="header">
Shop. Cat. Shop. Cat.
</f:facet> </f:facet>
<p:autoComplete <h:outputText
id="shopCat" id="shopCat"
value="#{item.shopCat}" value="#{item.shopCat}"
rendered="#{not item.ingGroup}" rendered="#{not item.ingGroup}"
editable="true" />
forceSelection="false"
autoSelection="false"
dropdown="true"
cache="true"
title="Note that changing Shopping category for an ingredient key changes it for all users of that key."
completeMethod="#{recipeDetailBean.shopcatList}"
>
<p:ajax event="blur"
listener="#{recipeDetailBean.ajaxShopcat}"
/>
</p:autoComplete>
</p:column> </p:column>
</p:dataTable> </p:dataTable>
</h:panelGrid> </h:panelGrid>