|
@ -16,14 +16,19 @@ import org.apache.commons.lang3.tuple.Pair; |
|
|
import org.springframework.data.domain.Page; |
|
|
import org.springframework.data.domain.Page; |
|
|
import org.springframework.data.domain.PageRequest; |
|
|
import org.springframework.data.domain.PageRequest; |
|
|
import org.springframework.data.jpa.domain.Specification; |
|
|
import org.springframework.data.jpa.domain.Specification; |
|
|
|
|
|
import org.springframework.scheduling.annotation.Scheduled; |
|
|
import org.springframework.stereotype.Service; |
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
|
|
|
|
import javax.annotation.PostConstruct; |
|
|
import javax.annotation.Resource; |
|
|
import javax.annotation.Resource; |
|
|
import javax.persistence.criteria.Predicate; |
|
|
import javax.persistence.criteria.Predicate; |
|
|
import java.math.BigDecimal; |
|
|
import java.math.BigDecimal; |
|
|
import java.math.RoundingMode; |
|
|
import java.math.RoundingMode; |
|
|
import java.text.DecimalFormat; |
|
|
import java.text.DecimalFormat; |
|
|
|
|
|
import java.time.Instant; |
|
|
import java.util.*; |
|
|
import java.util.*; |
|
|
|
|
|
import java.util.concurrent.locks.Lock; |
|
|
|
|
|
import java.util.concurrent.locks.ReentrantLock; |
|
|
import java.util.stream.Collectors; |
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
|
@Slf4j |
|
|
@Slf4j |
|
@ -32,6 +37,9 @@ public class DishService { |
|
|
private static final List<String> MUST_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sodium"); |
|
|
private static final List<String> MUST_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sodium"); |
|
|
private static final List<String> WANT_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sugar", "sodium"); |
|
|
private static final List<String> WANT_DISPLAY_ITEM = Lists.newArrayList("energy", "protein", "fat", "carbs", "sugar", "sodium"); |
|
|
|
|
|
|
|
|
|
|
|
private static final Lock UPDATE_LABEL_LOCK = new ReentrantLock(); |
|
|
|
|
|
private static Instant UPDATE_LABEL_TIME; |
|
|
|
|
|
|
|
|
@Resource |
|
|
@Resource |
|
|
private EnumService enumService; |
|
|
private EnumService enumService; |
|
|
|
|
|
|
|
@ -41,6 +49,41 @@ public class DishService { |
|
|
@Resource |
|
|
@Resource |
|
|
private DishRepository dishRepository; |
|
|
private DishRepository dishRepository; |
|
|
|
|
|
|
|
|
|
|
|
@Scheduled(cron = "0/5 * * * * *") |
|
|
|
|
|
public void init() { |
|
|
|
|
|
if (!UPDATE_LABEL_LOCK.tryLock()) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
try { |
|
|
|
|
|
List<Dish> dishes = UPDATE_LABEL_TIME == null ? dishRepository.findAll() : dishRepository.findByModifyGreaterThan(UPDATE_LABEL_TIME); |
|
|
|
|
|
Map<String, Ingredient> ingredientMap = ingredientService.getFullByKeys(dishes.stream().filter(x -> CollectionUtils.isNotEmpty(x.getIngredient())).flatMap(x -> x.getIngredient().stream().map(DishItemDTO::getKey)).collect(Collectors.toSet())).stream().collect(Collectors.toMap(Ingredient::getKey, v -> v)); |
|
|
|
|
|
dishes.forEach(dish -> { |
|
|
|
|
|
Map<String, BigDecimal> 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))) |
|
|
|
|
|
).collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); |
|
|
|
|
|
items.put("sugar", sugar(dish, ingredientMap)); |
|
|
|
|
|
|
|
|
|
|
|
List<String> label = Lists.newArrayList(); |
|
|
|
|
|
if (items.getOrDefault("sodium", BigDecimal.ZERO).compareTo(new BigDecimal("120")) <= 0) { |
|
|
|
|
|
label.add("低盐"); |
|
|
|
|
|
} |
|
|
|
|
|
if (items.getOrDefault("fat", BigDecimal.ZERO).compareTo(new BigDecimal("3")) <= 0) { |
|
|
|
|
|
label.add("低脂"); |
|
|
|
|
|
} |
|
|
|
|
|
if (items.getOrDefault("sugar", BigDecimal.ZERO).compareTo(new BigDecimal("5")) <= 0) { |
|
|
|
|
|
label.add("低糖"); |
|
|
|
|
|
} |
|
|
|
|
|
dish.setLabel(label); |
|
|
|
|
|
}); |
|
|
|
|
|
dishRepository.saveAll(dishes); |
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
log.error("[DishService] update label exception : " + e.getMessage(), e); |
|
|
|
|
|
} finally { |
|
|
|
|
|
UPDATE_LABEL_TIME = Instant.now(); |
|
|
|
|
|
UPDATE_LABEL_LOCK.unlock(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public void add(List<Dish> dishes, String operator) { |
|
|
public void add(List<Dish> dishes, String operator) { |
|
|
dishRepository.saveAll(dishes); |
|
|
dishRepository.saveAll(dishes); |
|
|
log.info("[DishService] add dishes count = " + dishes.size() + ", operator = " + operator); |
|
|
log.info("[DishService] add dishes count = " + dishes.size() + ", operator = " + operator); |
|
@ -85,11 +128,11 @@ public class DishService { |
|
|
return dishRepository.findByNameLikeOrderByIdDesc("%" + keyword + "%"); |
|
|
return dishRepository.findByNameLikeOrderByIdDesc("%" + keyword + "%"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public Page<Dish> list(Long vender, String name, String mark, String poly, PageRequest pageRequest) { |
|
|
public Page<Dish> list(Long vender, String name, String mark, String poly, String label, PageRequest pageRequest) { |
|
|
return dishRepository.findAll(toSpecification(vender, name, mark, poly), pageRequest); |
|
|
return dishRepository.findAll(toSpecification(vender, name, mark, poly, label), pageRequest); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private Specification<Dish> toSpecification(Long vender, String name, String mark, String poly) { |
|
|
private Specification<Dish> toSpecification(Long vender, String name, String mark, String poly, String label) { |
|
|
return (root, query, builder) -> { |
|
|
return (root, query, builder) -> { |
|
|
List<Predicate> predicates = new ArrayList<>(); |
|
|
List<Predicate> predicates = new ArrayList<>(); |
|
|
|
|
|
|
|
@ -109,6 +152,10 @@ public class DishService { |
|
|
predicates.add(builder.like(root.get("name"), "%" + name + "%")); |
|
|
predicates.add(builder.like(root.get("name"), "%" + name + "%")); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (StringUtils.isNotBlank(label)) { |
|
|
|
|
|
predicates.add(builder.like(root.get("label"), "%" + label + "%")); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (predicates.size() > 1) { |
|
|
if (predicates.size() > 1) { |
|
|
return builder.and(predicates.toArray(new Predicate[0])); |
|
|
return builder.and(predicates.toArray(new Predicate[0])); |
|
|
} else if (predicates.size() == 1) { |
|
|
} else if (predicates.size() == 1) { |
|
@ -167,9 +214,7 @@ public class DishService { |
|
|
} |
|
|
} |
|
|
}, BigDecimal::add)); |
|
|
}, BigDecimal::add)); |
|
|
|
|
|
|
|
|
items.put("sugar", dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())) |
|
|
items.put("sugar", sugar(dish, ingredientMap)); |
|
|
.map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue())) |
|
|
|
|
|
.filter(x -> StringUtils.equals("糖类", x.getKey().getType())).map(Pair::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO)); |
|
|
|
|
|
|
|
|
|
|
|
MUST_DISPLAY_ITEM.forEach(x -> { |
|
|
MUST_DISPLAY_ITEM.forEach(x -> { |
|
|
if (!items.containsKey(x)) { |
|
|
if (!items.containsKey(x)) { |
|
@ -201,4 +246,10 @@ public class DishService { |
|
|
return DishLabelDO.builder().name(dish.getName()).ingredients(ingredients).component(component).build(); |
|
|
return DishLabelDO.builder().name(dish.getName()).ingredients(ingredients).component(component).build(); |
|
|
}).collect(Collectors.toList()); |
|
|
}).collect(Collectors.toList()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private BigDecimal sugar(Dish dish, Map<String, Ingredient> ingredientMap) { |
|
|
|
|
|
return dish.getIngredient().stream().filter(x -> ingredientMap.containsKey(x.getKey())) |
|
|
|
|
|
.map(x -> Pair.of(ingredientMap.get(x.getKey()), x.getValue())) |
|
|
|
|
|
.filter(x -> StringUtils.equals("糖类", x.getKey().getType())).map(Pair::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); |
|
|
|
|
|
} |
|
|
} |
|
|
} |