From 351861f80c633b23a12780e302e2e4f412ee6e7c Mon Sep 17 00:00:00 2001 From: fangyang2021 <3020949587@qq.com> Date: Mon, 10 Mar 2025 11:07:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9C=80=E6=B1=82=E6=9B=B4=E6=96=B02025.3.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mathvision/diet/domain/DishLabelDO.java | 2 + .../mathvision/diet/service/DishService.java | 32 ++++--- .../diet/service/MenuReportService.java | 92 +++++++++++-------- .../diet/domian/NutritionSortEnum.java | 62 +++++++++++++ .../diet/controller/DishController.java | 33 ++++--- doc/change.md | 5 + doc/dish.md | 25 ++++- doc/menu/report.md | 6 +- 8 files changed, 193 insertions(+), 64 deletions(-) create mode 100644 diet-dao/src/main/java/com/mathvision/diet/domian/NutritionSortEnum.java diff --git a/diet-core/src/main/java/com/mathvision/diet/domain/DishLabelDO.java b/diet-core/src/main/java/com/mathvision/diet/domain/DishLabelDO.java index 4cac6a7..ea9cbb3 100644 --- a/diet-core/src/main/java/com/mathvision/diet/domain/DishLabelDO.java +++ b/diet-core/src/main/java/com/mathvision/diet/domain/DishLabelDO.java @@ -15,4 +15,6 @@ public class DishLabelDO { String name; List component; List ingredients; + //update 新增三低标识 + List label; } diff --git a/diet-core/src/main/java/com/mathvision/diet/service/DishService.java b/diet-core/src/main/java/com/mathvision/diet/service/DishService.java index fb37025..68dfddf 100644 --- a/diet-core/src/main/java/com/mathvision/diet/service/DishService.java +++ b/diet-core/src/main/java/com/mathvision/diet/service/DishService.java @@ -109,7 +109,7 @@ public class DishService { log.info("[DishService] add dishes count = " + dishes.size() + ", operator = " + operator); } - public void delete(List ids, Long venderId,String operator) { + public void delete(List ids, Long venderId, String operator) { if (venderId > 0) { dishRepository.deleteByIdInAndVender(ids, venderId); } else { @@ -118,7 +118,7 @@ public class DishService { log.info("[DishService] delete ids = " + ids + ", operator = " + operator); } - public void delete(Long venderId,String operator) { + public void delete(Long venderId, String operator) { dishRepository.deleteByVender(venderId); log.info("[DishService] delete venderId = " + venderId + ", operator = " + operator); } @@ -221,7 +221,7 @@ public class DishService { List ingredients = dish.getIngredient().stream().filter(item -> BooleanUtils.isTrue(item.getIsMain())).map(DishItemDTO::getKey).filter(ingredientMap::containsKey).map(x -> ingredientMap.get(x).getName()).collect(Collectors.toList()); Map _items = dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())).flatMap(x -> - ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue()).divide(new BigDecimal(100), RoundingMode.HALF_UP))) + ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue()).divide(new BigDecimal(100), RoundingMode.HALF_UP))) ).filter(x -> x.getValue() != null && x.getValue().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); _items.put("sugar", sugar(dish, ingredientMap)); MUST_DISPLAY_ITEM.forEach(x -> { @@ -232,13 +232,17 @@ public class DishService { Map items = _items.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> { switch (v.getKey()) { - case "protein" : - case "fat" : - case "carbs" : - case "sugar" : return v.getValue().compareTo(new BigDecimal("0.5")) > 0 ? v.getValue() : BigDecimal.ZERO; - case "energy" : return v.getValue().compareTo(new BigDecimal("4")) > 0 ? v.getValue() : BigDecimal.ZERO; - case "sodium" : return v.getValue().compareTo(new BigDecimal("5")) > 0 ? v.getValue() : BigDecimal.ZERO; - default: return v.getValue(); + case "protein": + case "fat": + case "carbs": + case "sugar": + return v.getValue().compareTo(new BigDecimal("0.5")) > 0 ? v.getValue() : BigDecimal.ZERO; + case "energy": + return v.getValue().compareTo(new BigDecimal("4")) > 0 ? v.getValue() : BigDecimal.ZERO; + case "sodium": + return v.getValue().compareTo(new BigDecimal("5")) > 0 ? v.getValue() : BigDecimal.ZERO; + default: + return v.getValue(); } })); @@ -253,7 +257,10 @@ public class DishService { } String name = foodNutrient.getValue(); - String value = String.format("%s(%s)", formatValue.format(x.getValue().floatValue()), foodNutrient.getMeasurement() == null ? "-" : foodNutrient.getMeasurement()); + //String value = String.format("%s(%s)", formatValue.format(x.getValue().floatValue()), foodNutrient.getMeasurement() == null ? "-" : foodNutrient.getMeasurement()); + //update 能量需要单独做去小数点四舍五入 + String value = String.format("%s(%s)", "energy".equals(x.getKey()) ? formatInteger.format(x.getValue().floatValue()) : formatValue.format(x.getValue().floatValue()), foodNutrient.getMeasurement() == null ? "-" : foodNutrient.getMeasurement()); + String nrv = foodNutrient.getNrv() == null || foodNutrient.getNrv().floatValue() == 0 ? "-" : String.format("%s%%", formatInteger.format(x.getValue().divide(foodNutrient.getNrv(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)))); if (StringUtils.equalsIgnoreCase(x.getKey(), "sodium")) { float salt = x.getValue().multiply(new BigDecimal("0.0025")).floatValue(); @@ -262,8 +269,7 @@ public class DishService { } return ComponentAnalysisDO.builder().key(x.getKey()).name(name).nutrition(value).nrv(nrv).build(); }).collect(Collectors.toList()); - - return DishLabelDO.builder().name(dish.getName()).ingredients(ingredients).component(component).build(); + return DishLabelDO.builder().name(dish.getName()).ingredients(ingredients).component(component).label(dish.getLabel()).build(); }).collect(Collectors.toList()); } diff --git a/diet-core/src/main/java/com/mathvision/diet/service/MenuReportService.java b/diet-core/src/main/java/com/mathvision/diet/service/MenuReportService.java index 0011cdb..9394538 100644 --- a/diet-core/src/main/java/com/mathvision/diet/service/MenuReportService.java +++ b/diet-core/src/main/java/com/mathvision/diet/service/MenuReportService.java @@ -8,10 +8,7 @@ import com.alibaba.fastjson2.TypeReference; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Range; -import com.mathvision.diet.domian.MealType; -import com.mathvision.diet.domian.MeasurementType; -import com.mathvision.diet.domian.MenuDishItemDTO; -import com.mathvision.diet.domian.RuleItemDTO; +import com.mathvision.diet.domian.*; import com.mathvision.diet.entity.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -24,10 +21,8 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; @Slf4j @@ -57,7 +52,12 @@ public class MenuReportService { .flatMap(dish -> dish.getIngredient().stream().filter(item -> item.getValue().containsKey(crow) && item.getValue().get(crow).doubleValue() > 0 && ingredientMap.containsKey(item.getKey()))) .flatMap(x -> ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue().get(crow)).divide(new BigDecimal(100), RoundingMode.HALF_UP)))) .collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); - Map types = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> ingredientMap.get(item.getKey()).getType())).collect(Collectors.toMap(x -> x, x -> 1, Integer::sum)); + //Map types = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> ingredientMap.get(item.getKey()).getType())).collect(Collectors.toMap(x -> x, x -> 1, Integer::sum)); + + //update 今日食材种类改成标准的四种分类,去除烹调油、调味品。按照【谷薯杂豆类】【蔬菜水果】【畜禽鱼蛋】【奶豆坚果类】 + Map categoryType = new HashMap<>(); + nutrition.getFoodCategoryDay().forEach(foodCategoryDay -> foodCategoryDay.getCategory().forEach(category -> categoryType.put(category, foodCategoryDay.getName()))); + Map types = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> ingredientMap.get(item.getKey()).getType()).filter(categoryType::containsKey).map(categoryType::get)).collect(Collectors.toMap(categoryName -> categoryName, categoryName -> 1, Integer::sum)); itemStandard.forEach((key, value) -> { if (!items.containsKey(key)) { @@ -93,7 +93,7 @@ public class MenuReportService { } JSONObject content = new JSONObject(); content.put("nutrition", String.format("%s/%s", foodNutrient.getValue(), foodNutrient.getMeasurement())); - content.put("virtual", value); + content.put("virtual", "energy".equals(key) ? value.setScale(0, RoundingMode.HALF_UP) : value); Map standard = itemStandard.get(key); BigDecimal max = standard == null ? null : standard.get("max"); @@ -133,9 +133,9 @@ public class MenuReportService { content.put("overload", "-"); content.put("conclusion", "适量"); } else { - if(value.compareTo(max) > 0) { + if (value.compareTo(max) > 0) { byMax = true; - } else { + } else { byMin = true; } } @@ -145,7 +145,7 @@ public class MenuReportService { if (byMin) { BigDecimal overload = calculatePercentage(value, min); content.put("overload", overload + "%"); - if(overload.abs().compareTo(overflow) > 0) { + if (overload.abs().compareTo(overflow) > 0) { content.put("conclusion", "不足"); } else { content.put("conclusion", "适量"); @@ -155,8 +155,8 @@ public class MenuReportService { if (byMax) { BigDecimal overload = calculatePercentage(value, max); content.put("overload", overload + "%"); - if(overload.compareTo(overflow) > 0) { - if(ul != null && value.compareTo(ul) > 0) { + if (overload.compareTo(overflow) > 0) { + if (ul != null && value.compareTo(ul) > 0) { content.put("conclusion", "严重超标"); } else { content.put("conclusion", "过量"); @@ -168,7 +168,10 @@ public class MenuReportService { contents.add(content); }); - result.put("ingredient", contents); + + // update 按规则排序 + JSONArray sortContents = NutritionSortEnum.sortByRule(contents); + result.put("ingredient", sortContents); return result; } @@ -181,6 +184,7 @@ public class MenuReportService { Map ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(MenuDishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); Map, Integer> typesDay = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> Pair.of(dish.getDay(), ingredientMap.get(item.getKey()).getType()))).collect(Collectors.toMap(x -> x, x -> 1, Integer::sum)); Map, BigDecimal> weightDay = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> Triple.of(dish.getDay(), ingredientMap.get(item.getKey()).getType(), item.getValue().getOrDefault(crow, BigDecimal.ZERO)))).collect(Collectors.toMap(x -> Pair.of(x.getLeft(), x.getMiddle()), Triple::getRight, BigDecimal::add)); + Map, String> ingredientDetailsDay = dishes.stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> ingredientMap.containsKey(item.getKey())).map(item -> Triple.of(dish.getDay(), ingredientMap.get(item.getKey()).getType(), ingredientMap.get(item.getKey()).getName()))).collect(Collectors.toMap(x -> Pair.of(x.getLeft(), x.getMiddle()), Triple::getRight,(existing, replacement) -> existing + ", " + replacement)); Map dayRule = Maps.newHashMap(); dishes.stream().map(MenuDish::getDay).forEach(day -> dayRule.put(day, dayStandard.stream().map(standard -> { @@ -188,6 +192,8 @@ public class MenuReportService { content.put("day", day); content.put("name", standard.getName()); content.put("standard", standard.getRange()); + String details = ingredientDetailsDay.entrySet().stream().filter(x -> x.getKey().getKey().equals(day) && standard.getCategory().contains(x.getKey().getValue())).map(Map.Entry::getValue).collect(Collectors.joining(",")); + content.put("details", details); if (MeasurementType.quantity.equals(standard.getType())) { long supplied = typesDay.entrySet().stream().filter(x -> x.getKey().getKey().equals(day) && standard.getCategory().contains(x.getKey().getValue())).map(Map.Entry::getValue).reduce(Integer::sum).orElse(0); content.put("measurement", standard.getType()); @@ -206,6 +212,8 @@ public class MenuReportService { JSONObject content = new JSONObject(); content.put("name", standard.getName()); content.put("standard", standard.getRange()); + String details = ingredientDetailsDay.entrySet().stream().filter(x -> standard.getCategory().contains(x.getKey().getValue())).map(Map.Entry::getValue).collect(Collectors.joining(",")); + content.put("details", details); if (MeasurementType.quantity.equals(standard.getType())) { long supplied = typesDay.entrySet().stream().filter(x -> standard.getCategory().contains(x.getKey().getValue())).map(Map.Entry::getValue).reduce(Integer::sum).orElse(0); content.put("measurement", standard.getType()); @@ -238,7 +246,7 @@ public class MenuReportService { } public JSONObject energy(long day, String crow, List dishes) { - List allConcerned= Lists.newArrayList("protein", "fat", "carbs"); + List allConcerned = Lists.newArrayList("protein", "fat", "carbs"); Map ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(MenuDishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); Map items = dishes.stream() .flatMap(dish -> dish.getIngredient().stream().filter(item -> item.getValue().containsKey(crow) && item.getValue().get(crow).doubleValue() > 0 && ingredientMap.containsKey(item.getKey()))) @@ -281,17 +289,17 @@ public class MenuReportService { Map ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(MenuDishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); Map salt = dishes.stream().collect(Collectors.groupingBy(MenuDish::getDay)).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> item.getValue().containsKey(crow) && item.getValue().get(crow).doubleValue() > 0 && ingredientMap.containsKey(item.getKey()))) - .flatMap(x -> ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue().get(crow)).divide(new BigDecimal(100), RoundingMode.HALF_UP)))) - .filter(x -> StringUtils.equalsIgnoreCase("sodium", x.getKey())) - .map(x -> x.getValue().multiply(new BigDecimal("0.0025"))) - .reduce(BigDecimal :: add) - .orElse(BigDecimal.ZERO))); + .flatMap(x -> ingredientMap.get(x.getKey()).getNutrient().entrySet().stream().map(n -> Pair.of(n.getKey(), n.getValue().multiply(x.getValue().get(crow)).divide(new BigDecimal(100), RoundingMode.HALF_UP)))) + .filter(x -> StringUtils.equalsIgnoreCase("sodium", x.getKey())) + .map(x -> x.getValue().multiply(new BigDecimal("0.0025"))) + .reduce(BigDecimal::add) + .orElse(BigDecimal.ZERO))); Map sugar = dishes.stream().collect(Collectors.groupingBy(MenuDish::getDay)).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().stream().flatMap(dish -> dish.getIngredient().stream().filter(item -> item.getValue().containsKey(crow) && item.getValue().get(crow).doubleValue() > 0 && ingredientMap.containsKey(item.getKey())) - .map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue())) - .filter(x -> StringUtils.equals("糖类", x.getKey().getType())) - .map(x -> x.getValue().values().stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO)) + .map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue())) + .filter(x -> StringUtils.equals("糖类", x.getKey().getType())) + .map(x -> x.getValue().values().stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO)) ).reduce(BigDecimal::add).orElse(BigDecimal.ZERO))); Map oil = dishes.stream().collect(Collectors.groupingBy(MenuDish::getDay)).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, @@ -316,7 +324,7 @@ public class MenuReportService { headers.add(Lists.newArrayList("日均营养分析", "营养素")); headers.add(Lists.newArrayList("日均营养分析", "实际摄入")); headers.add(Lists.newArrayList("日均营养分析", "标准范围")); - headers.add(Lists.newArrayList("日均营养分析", "UL值")); + //headers.add(Lists.newArrayList("日均营养分析", "UL值")); headers.add(Lists.newArrayList("日均营养分析", "溢出范围")); headers.add(Lists.newArrayList("日均营养分析", "评价")); @@ -325,8 +333,8 @@ public class MenuReportService { if (ingredient == null) { return; } - - List> contents = ingredient.stream().map(x -> (JSONObject)x).map(x -> Lists.newArrayList(x.get("nutrition"), x.get("virtual"), x.get("standard"), x.get("ul"), x.get("overload"), x.get("conclusion"))).collect(Collectors.toList()); + //List> contents = ingredient.stream().map(x -> (JSONObject) x).map(x -> Lists.newArrayList(x.get("nutrition"), x.get("virtual"), x.get("standard"), x.get("ul"), x.get("overload"), x.get("conclusion"))).collect(Collectors.toList()); + List> contents = ingredient.stream().map(x -> (JSONObject) x).map(x -> Lists.newArrayList(x.get("nutrition"), x.get("virtual"), x.get("standard"), x.get("overload"), x.get("conclusion"))).collect(Collectors.toList()); excelWriter.write(contents, EasyExcel.writerSheet("日均营养分析-" + crow).head(headers).build()); }); @@ -342,7 +350,7 @@ public class MenuReportService { return; } - List> contents = energy.stream().map(x -> (JSONObject)x).map(x -> Lists.newArrayList(x.get("name"), x.get("standard"), x.get("value"), x.get("conclusion"))).collect(Collectors.toList()); + List> contents = energy.stream().map(x -> (JSONObject) x).map(x -> Lists.newArrayList(x.get("name"), x.get("standard"), x.get("value"), x.get("conclusion"))).collect(Collectors.toList()); excelWriter.write(contents, EasyExcel.writerSheet("日均能量来源分布-" + crow).head(headers).build()); }); @@ -352,6 +360,8 @@ public class MenuReportService { headers.add(Lists.newArrayList("食材种类统计", "种类名称")); headers.add(Lists.newArrayList("食材种类统计", "至少需要")); headers.add(Lists.newArrayList("食材种类统计", "当前含有")); + //update 《食材种类统计》表格增加包含食材明细清单 + headers.add(Lists.newArrayList("食材种类统计", "包含食材")); headers.add(Lists.newArrayList("食材种类统计", "还需")); JSONObject types = types(menu, crow, menuDishService.query(menu.getId(), menu.getVender())); @@ -361,12 +371,16 @@ public class MenuReportService { List> contents = Lists.newArrayList(); JSONArray weekRule = types.getJSONArray("weekRule"); + //update 《食材种类统计》表格“至少需要”一栏去掉单位“克”,包含食材明细; if (weekRule != null) { - contents.addAll(weekRule.stream().map(x -> (JSONObject)x).map(x -> Lists.newArrayList("周合计", x.get("name"), MeasurementType.quantity.name().equals(x.getString("measurement")) ? x.get("standard") + "种" : x.get("standard") + "克", x.get("supplied"), x.get("lack"))).collect(Collectors.toList())); + //contents.addAll(weekRule.stream().map(x -> (JSONObject) x).map(x -> Lists.newArrayList("周合计", x.get("name"), MeasurementType.quantity.name().equals(x.getString("measurement")) ? x.get("standard") + "种" : x.get("standard") + "克", x.get("supplied"), x.get("lack"))).collect(Collectors.toList())); + contents.addAll(weekRule.stream().map(x -> (JSONObject) x).map(x -> Lists.newArrayList("周合计", x.get("name"), x.get("standard"), x.get("supplied"), x.get("details"), x.get("lack"))).collect(Collectors.toList())); } - Map> dayRule = types.getObject("dayRule", new TypeReference>>() {}); + Map> dayRule = types.getObject("dayRule", new TypeReference>>() { + }); if (dayRule != null) { - dayRule.forEach((k, v) -> contents.addAll(v.stream().map(x -> Lists.newArrayList("周" + x.getString("day"), x.get("name"), MeasurementType.quantity.name().equals(x.getString("measurement")) ? x.get("standard") + "种" : x.get("standard") + "克", x.get("supplied"), x.get("lack"))).collect(Collectors.toList()))); + //dayRule.forEach((k, v) -> contents.addAll(v.stream().map(x -> Lists.newArrayList("周" + x.getString("day"), x.get("name"), MeasurementType.quantity.name().equals(x.getString("measurement")) ? x.get("standard") + "种" : x.get("standard") + "克", x.get("supplied"), x.get("lack"))).collect(Collectors.toList()))); + dayRule.forEach((k, v) -> contents.addAll(v.stream().map(x -> Lists.newArrayList("周" + x.getString("day"), x.get("name"), x.get("standard"), x.get("supplied"), x.get("details"), x.get("lack"))).collect(Collectors.toList()))); } excelWriter.write(contents, EasyExcel.writerSheet("食材种类统计-" + crow).head(headers).build()); }); @@ -382,7 +396,7 @@ public class MenuReportService { return; } - List> contents = polys.entrySet().stream().filter(kv -> StringUtils.isNumeric(kv.getKey())).map(kv -> ((Map)kv.getValue()).entrySet().stream().map(x -> Lists.newArrayList(kv.getKey().equals("0") ? "周合计" : "周" + kv.getKey(), x.getKey(), x.getValue())).collect(Collectors.toList())).flatMap(Collection::stream).collect(Collectors.toList()); + List> contents = polys.entrySet().stream().filter(kv -> StringUtils.isNumeric(kv.getKey())).map(kv -> ((Map) kv.getValue()).entrySet().stream().map(x -> Lists.newArrayList(kv.getKey().equals("0") ? "周合计" : "周" + kv.getKey(), x.getKey(), x.getValue())).collect(Collectors.toList())).flatMap(Collection::stream).collect(Collectors.toList()); excelWriter.write(contents, EasyExcel.writerSheet("烹饪方式统计-" + crow).head(headers).build()); }); } @@ -405,10 +419,14 @@ public class MenuReportService { VenderConfig config = venderService.queryConfig(menu.getVender()); BigDecimal scale = menu.getMeals().stream().map(MealType::toType).distinct().map(x -> { switch (x) { - case breakfast: return config.getBreakfast(); - case lunch: return config.getLunch(); - case dinner: return config.getDinner(); - default: return BigDecimal.ZERO; + case breakfast: + return config.getBreakfast(); + case lunch: + return config.getLunch(); + case dinner: + return config.getDinner(); + default: + return BigDecimal.ZERO; } }).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); diff --git a/diet-dao/src/main/java/com/mathvision/diet/domian/NutritionSortEnum.java b/diet-dao/src/main/java/com/mathvision/diet/domian/NutritionSortEnum.java new file mode 100644 index 0000000..ca08627 --- /dev/null +++ b/diet-dao/src/main/java/com/mathvision/diet/domian/NutritionSortEnum.java @@ -0,0 +1,62 @@ +package com.mathvision.diet.domian; + +import java.util.*; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; + +/** + * @author fy + * @description: 营养素排序枚举 + */ +public enum NutritionSortEnum { + ENERGY("能量/kcal"), + PROTEIN("蛋白质/g"), + FAT("脂肪/g"), + CARBOHYDRATE("碳水化合物/g"), + CALCIUM("钙/mg"), + IRON("铁/mg"), + ZINC("锌/mg"), + VITAMIN_A("维生素A/μgRAE"), + VITAMIN_B1("维生素B1/mg"), + VITAMIN_B2("维生素B2/mg"), + VITAMIN_C("维生素C/mg"), + DIETARY_FIBER("膳食纤维/g"), + SODIUM("钠/mg"); + + private final String label; + private static final Map nutritionOrder = new HashMap<>(); + + static { + for (int index = 0; index < values().length; index++) { + nutritionOrder.put(values()[index].label, index); + } + } + + NutritionSortEnum(String label) { + this.label = label; + } + + public static Comparator getComparator() { + return (nutrition1, nutrition2) -> { + Integer order1 = nutritionOrder.get(nutrition1); + Integer order2 = nutritionOrder.get(nutrition2); + return Comparator.comparingInt((Integer order) -> order == null ? Integer.MAX_VALUE : order) + .compare(order1, order2); + }; + } + + public static JSONArray sortByRule(JSONArray contents) { + List sortedList = new ArrayList<>(); + for (int i = 0; i < contents.size(); i++) { + sortedList.add(contents.getJSONObject(i)); + } + + sortedList.sort((o1, o2) -> { + String nutrition1 = o1 instanceof JSONObject ? o1.getString("nutrition") : null; + String nutrition2 = o2 instanceof JSONObject ? o2.getString("nutrition") : null; + return getComparator().compare(nutrition1, nutrition2); + }); + + return new JSONArray(sortedList); + } +} \ No newline at end of file diff --git a/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java b/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java index 78f6060..cf6e4c1 100644 --- a/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java +++ b/diet-web/src/main/java/com/mathvision/diet/controller/DishController.java @@ -29,7 +29,7 @@ import java.util.stream.Collectors; @RequestMapping("/api/dish") @Controller -public class DishController extends BaseController { +public class DishController extends BaseController { @Resource EnumService enumService; @@ -54,7 +54,8 @@ public class DishController extends BaseController { Assert.isTrue(CollectionUtils.isNotEmpty(month) && month.stream().allMatch(x -> Range.closed(1, 12).contains(x)), "[参数错误]请选择正确的月份!"); Assert.isTrue(JSON.isValid(ingredient), "[参数错误]食材列表必填!"); - List items = JSON.parseObject(ingredient, new TypeReference>(){}); + List items = JSON.parseObject(ingredient, new TypeReference>() { + }); Assert.isTrue(items.stream().allMatch(x -> ingredientService.existsIngredientByKey(x.getKey())), "[参数错误]请选择系统存在的食材!"); if (isAdmin()) { Assert.isTrue(CollectionUtils.isNotEmpty(vendors), "[参数错误]单位列表必填!"); @@ -67,13 +68,22 @@ public class DishController extends BaseController { dishService.add(vendors.stream().map(vender -> Dish.builder().name(name).vender(vender).marks(mark).poly(poly).month(month).icon(icon).ingredient(items).operate(getUid()).created(dateTime).modify(dateTime).build()).collect(Collectors.toList()), getUid()); } + //update 新增修改菜品,名称做重复检测和提醒 + @ResponseBody + @RequestMapping(path = "check/name", method = RequestMethod.GET) + public boolean checkName(@RequestParam(required = false) Long id, @RequestParam Long vender, @RequestParam String name) { + Assert.isTrue(vender != null, "[参数错误]单位id必填!"); + Assert.isTrue(StringUtils.isNotBlank(name), "[参数错误]菜品名称必填!"); + return dishService.notExists(id, name, vender); + } + @ResponseBody @RequestMapping(path = "copy", method = RequestMethod.PUT) public void copy(@RequestParam Long id, @RequestParam(required = false) List vendors) { Dish dish = isAdmin() ? dishService.get(id) : dishService.get(id, getVender()); Assert.notNull(dish, "[参数错误]菜品不存在, 复制失败!"); - if(isAdmin()) { + if (isAdmin()) { vendors = vendors == null ? Lists.newArrayList() : vendors.stream().filter(venderService::exists).distinct().collect(Collectors.toList()); } else { vendors = Lists.newArrayList(getVender()); @@ -92,37 +102,38 @@ public class DishController extends BaseController { @ResponseBody @RequestMapping(method = RequestMethod.POST) public void update(@RequestParam Long id, @RequestParam(required = false) String name, @RequestParam(required = false) String icon, @RequestParam(required = false) List month, @RequestParam(required = false) String mark, @RequestParam(required = false) String poly, @RequestParam(required = false) String ingredient) { - Dish dish = isAdmin()? dishService.get(id) : dishService.get(id, getVender()); + Dish dish = isAdmin() ? dishService.get(id) : dishService.get(id, getVender()); Assert.isTrue(dish != null, "[参数错误]菜品不存在!"); boolean flag = false; - if(StringUtils.isNotBlank(name) && !StringUtils.equals(name, dish.getName())) { + if (StringUtils.isNotBlank(name) && !StringUtils.equals(name, dish.getName())) { Assert.isTrue(dishService.notExists(id, name, dish.getVender()), "[参数错误]菜品名称已存在!"); dish.setName(name); flag = true; } - if(StringUtils.isNotBlank(icon) && !icon.equals(dish.getIcon())) { + if (StringUtils.isNotBlank(icon) && !icon.equals(dish.getIcon())) { dish.setIcon(icon); flag = true; } - if(StringUtils.isNotBlank(mark) && !mark.equals(dish.getMarks())) { + if (StringUtils.isNotBlank(mark) && !mark.equals(dish.getMarks())) { Assert.isTrue(enumService.checkMark(mark), "[参数错误]菜品标签不在取值范围内!"); dish.setMarks(mark); flag = true; } - if(StringUtils.isNotBlank(poly) && !poly.equals(dish.getPoly())) { + if (StringUtils.isNotBlank(poly) && !poly.equals(dish.getPoly())) { Assert.isTrue(enumService.checkPoly(poly), "[参数错误]烹饪手法不在取值范围内!"); dish.setPoly(poly); flag = true; } - if(CollectionUtils.isNotEmpty(month)) { + if (CollectionUtils.isNotEmpty(month)) { Assert.isTrue(CollectionUtils.isNotEmpty(month) && month.stream().allMatch(x -> Range.closed(1, 12).contains(x)), "[参数错误]请选择正确的月份!"); dish.setMonth(month); flag = true; } if (JSON.isValid(ingredient)) { - List items = JSON.parseObject(ingredient, new TypeReference>(){}); - if(CollectionUtils.isNotEmpty(items)) { + List items = JSON.parseObject(ingredient, new TypeReference>() { + }); + if (CollectionUtils.isNotEmpty(items)) { Assert.isTrue(items.stream().allMatch(x -> ingredientService.existsIngredientByKey(x.getKey())), "[参数错误]请选择系统存在的食材!"); dish.setIngredient(items); flag = true; diff --git a/doc/change.md b/doc/change.md index c60575b..f33da17 100644 --- a/doc/change.md +++ b/doc/change.md @@ -64,3 +64,8 @@ ### 12.15 * 油盐糖接口: 增删改查; + +### 2025.3.7 +* 油盐糖接口(/api/dish/label): 返回值增加三低标签, 字段名-label, 类型-list; +* 类型分析接口(/api/menu/analysis/types): 食谱详情-营养分析-食材种类, dayRule和weekRule返回list结果中每项元素,新增食材明细-details字段,类型-string; +* 新增菜品名称重复校验接口(/api/dish/check/name)。 \ No newline at end of file diff --git a/doc/dish.md b/doc/dish.md index 74ab10e..3a8e3c4 100644 --- a/doc/dish.md +++ b/doc/dish.md @@ -192,6 +192,7 @@ ids=1,2,3 // 传了ID返回指定标签,不传返回所有菜品的标签列 "ingredients": [ "小麦" ], + "label": ["低盐", "低脂", "低糖"], "name": "番茄炒鸡蛋" } ], @@ -285,4 +286,26 @@ id=1 // 源菜品编号, 必填 "desc": "成功", "success": true } -~~~ \ No newline at end of file +~~~ + +# 9. 名称重复校验 + + +> GET /api/dish/check/name + +### 输入: +```text +id=47 // 菜品id, 非必填 +vender=1 // 单位id,必填 +name=回锅肉 // 菜品名称,必填 +``` + +### 输出: +~~~json +{ + "body": false, // true:不重复,名称有效; false:重复 + "code": 200, + "desc": "成功", + "success": true +} +~~~ diff --git a/doc/menu/report.md b/doc/menu/report.md index 9eb9cc4..adbf56d 100644 --- a/doc/menu/report.md +++ b/doc/menu/report.md @@ -218,7 +218,8 @@ crow=xxx // "standard": "10~100", "measurement": "weight", "supplied": 320, - "lack": -220 + "lack": -220, + "details": "[(ֵ), , ]" } ] }, @@ -228,7 +229,8 @@ crow=xxx // "standard": "10~100", "measurement": "weight", "supplied": 320, - "lack": -220 + "lack": -220, + "details": "[(ֵ), , ]" } ] },