commit
0130a26503
165 changed files with 16369 additions and 0 deletions
@ -0,0 +1,37 @@ |
|||||
|
target/ |
||||
|
!.mvn/wrapper/maven-wrapper.jar |
||||
|
!**/src/main/**/target/ |
||||
|
!**/src/test/**/target/ |
||||
|
|
||||
|
### IntelliJ IDEA ### |
||||
|
.idea/ |
||||
|
.jpb/ |
||||
|
*.iws |
||||
|
*.iml |
||||
|
*.ipr |
||||
|
logs/ |
||||
|
|
||||
|
### Eclipse ### |
||||
|
.apt_generated |
||||
|
.classpath |
||||
|
.factorypath |
||||
|
.project |
||||
|
.settings |
||||
|
.springBeans |
||||
|
.sts4-cache |
||||
|
|
||||
|
### NetBeans ### |
||||
|
/nbproject/private/ |
||||
|
/nbbuild/ |
||||
|
/dist/ |
||||
|
/nbdist/ |
||||
|
/.nb-gradle/ |
||||
|
build/ |
||||
|
!**/src/main/**/build/ |
||||
|
!**/src/test/**/build/ |
||||
|
|
||||
|
### VS Code ### |
||||
|
.vscode/ |
||||
|
|
||||
|
### Mac OS ### |
||||
|
.DS_Store!/ |
||||
@ -0,0 +1,58 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
|
||||
|
<groupId>com.mathvision.diet</groupId> |
||||
|
<artifactId>diet-core</artifactId> |
||||
|
<version>1.0-SNAPSHOT</version> |
||||
|
|
||||
|
<properties> |
||||
|
<maven.compiler.source>8</maven.compiler.source> |
||||
|
<maven.compiler.target>8</maven.compiler.target> |
||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
</properties> |
||||
|
|
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>com.mathvision.diet</groupId> |
||||
|
<artifactId>diet-dao</artifactId> |
||||
|
<version>1.0-SNAPSHOT</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.alibaba</groupId> |
||||
|
<artifactId>easyexcel</artifactId> |
||||
|
<version>3.3.2</version> |
||||
|
<exclusions> |
||||
|
<exclusion> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi-ooxml</artifactId> |
||||
|
</exclusion> |
||||
|
<exclusion> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi-ooxml-schemas</artifactId> |
||||
|
</exclusion> |
||||
|
<exclusion> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi</artifactId> |
||||
|
</exclusion> |
||||
|
</exclusions> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.deepoove</groupId> |
||||
|
<artifactId>poi-tl</artifactId> |
||||
|
<version>1.12.2</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi</artifactId> |
||||
|
<version>5.2.2</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>io.github.draco1023</groupId> |
||||
|
<artifactId>poi-tl-ext</artifactId> |
||||
|
<version>0.4.15</version> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
</project> |
||||
@ -0,0 +1,17 @@ |
|||||
|
package com.mathvision.diet.domain; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
@Builder |
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
public class ComponentAnalysisDO { |
||||
|
String key; |
||||
|
String name; |
||||
|
String nutrition; |
||||
|
String nrv; |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.mathvision.diet.domain; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
@Builder |
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
public class DishLabelDO { |
||||
|
String name; |
||||
|
List<ComponentAnalysisDO> component; |
||||
|
List<String> ingredients; |
||||
|
//update 新增三低标识
|
||||
|
List<String> label; |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
package com.mathvision.diet.domain; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.entity.RoleItem; |
||||
|
import com.mathvision.diet.entity.Vender; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Builder |
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
public class UserDO { |
||||
|
private String uid; |
||||
|
private String name; |
||||
|
private String phone; |
||||
|
private Vender vender; |
||||
|
private Long roleId; |
||||
|
private String roleName; |
||||
|
private String roleType; |
||||
|
private Instant time; |
||||
|
private List<RoleItem> roleItems; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
public boolean isAdmin() { |
||||
|
return vender == null || vender.getId() == null; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
package com.mathvision.diet.excel; |
||||
|
|
||||
|
import com.alibaba.excel.converters.Converter; |
||||
|
import com.alibaba.excel.enums.CellDataTypeEnum; |
||||
|
import com.alibaba.excel.metadata.GlobalConfiguration; |
||||
|
import com.alibaba.excel.metadata.data.ReadCellData; |
||||
|
import com.alibaba.excel.metadata.data.WriteCellData; |
||||
|
import com.alibaba.excel.metadata.property.ExcelContentProperty; |
||||
|
import com.alibaba.excel.util.NumberUtils; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
@Slf4j |
||||
|
public class BigDecimalStringConverter implements Converter<BigDecimal> { |
||||
|
public BigDecimalStringConverter() { |
||||
|
} |
||||
|
|
||||
|
public Class<BigDecimal> supportJavaTypeKey() { |
||||
|
return BigDecimal.class; |
||||
|
} |
||||
|
|
||||
|
public CellDataTypeEnum supportExcelTypeKey() { |
||||
|
return CellDataTypeEnum.STRING; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
||||
|
if(cellData == null) { |
||||
|
return null; |
||||
|
} |
||||
|
if(CellDataTypeEnum.NUMBER.equals(cellData.getType())) { |
||||
|
return cellData.getNumberValue(); |
||||
|
} |
||||
|
if (CellDataTypeEnum.STRING.equals(cellData.getType())) { |
||||
|
try { |
||||
|
return NumberUtils.parseBigDecimal(cellData.getStringValue().trim(), contentProperty); |
||||
|
} catch (Exception e) { |
||||
|
log.error("[BigDecimalStringConverter] convertToJavaData<" + cellData.getStringValue() + "> exception :" + e.getMessage(), e); |
||||
|
return new BigDecimal(-1); |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public WriteCellData<?> convertToExcelData(BigDecimal value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
||||
|
return NumberUtils.formatToCellDataString(value, contentProperty); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
package com.mathvision.diet.excel; |
||||
|
|
||||
|
import com.alibaba.excel.annotation.ExcelProperty; |
||||
|
import com.alibaba.excel.annotation.write.style.*; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
@Builder |
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
@HeadRowHeight(30) |
||||
|
@ContentRowHeight(15) |
||||
|
@ColumnWidth(25) |
||||
|
@ContentFontStyle(fontHeightInPoints = (short) 12) |
||||
|
public class IngredientModel { |
||||
|
|
||||
|
@ExcelProperty("食物编码") |
||||
|
private String key; |
||||
|
|
||||
|
@ExcelProperty("食物名称") |
||||
|
private String name; |
||||
|
|
||||
|
@ExcelProperty("食物类型") |
||||
|
private String type; |
||||
|
|
||||
|
@ExcelProperty(value = "能量(kcal)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal energy; |
||||
|
|
||||
|
@ExcelProperty(value = "蛋白质(g)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal protein; |
||||
|
|
||||
|
@ExcelProperty(value = "脂肪(g)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal fat; |
||||
|
|
||||
|
@ExcelProperty(value = "碳水化合物(g)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal carbs; |
||||
|
|
||||
|
@ExcelProperty(value = "钙(mg)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal calcium; |
||||
|
|
||||
|
@ExcelProperty(value = "铁(mg)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal iron; |
||||
|
|
||||
|
@ExcelProperty(value = "锌(mg)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal zinc; |
||||
|
|
||||
|
@ExcelProperty(value = "维生素A(μgRAE)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal va; |
||||
|
|
||||
|
@ExcelProperty(value = "维生素B1(mg)硫胺素", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal vb1; |
||||
|
|
||||
|
@ExcelProperty(value = "维生素B2(mg)核黄素", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal vb2; |
||||
|
|
||||
|
@ExcelProperty(value = "维生素C(mg)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal vc; |
||||
|
|
||||
|
@ExcelProperty(value = "膳食纤维(g)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal fiber; |
||||
|
|
||||
|
@ExcelProperty(value = "钠(mg)", converter = BigDecimalStringConverter.class) |
||||
|
private BigDecimal sodium; |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
package com.mathvision.diet.excel; |
||||
|
|
||||
|
import com.alibaba.excel.annotation.ExcelProperty; |
||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth; |
||||
|
import com.alibaba.excel.annotation.write.style.ContentFontStyle; |
||||
|
import com.alibaba.excel.annotation.write.style.ContentRowHeight; |
||||
|
import com.alibaba.excel.annotation.write.style.HeadRowHeight; |
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.Builder; |
||||
|
import lombok.Data; |
||||
|
import lombok.NoArgsConstructor; |
||||
|
|
||||
|
@Builder |
||||
|
@Data |
||||
|
@NoArgsConstructor |
||||
|
@AllArgsConstructor |
||||
|
@HeadRowHeight(30) |
||||
|
@ContentRowHeight(15) |
||||
|
@ColumnWidth(18) |
||||
|
@ContentFontStyle(fontHeightInPoints = (short) 12) |
||||
|
public class ResultModel { |
||||
|
|
||||
|
@ColumnWidth(80) |
||||
|
@ExcelProperty("数据标识") |
||||
|
private String key; |
||||
|
|
||||
|
@ColumnWidth(35) |
||||
|
@ExcelProperty("导入结果") |
||||
|
private String result; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.google.common.util.concurrent.RateLimiter; |
||||
|
import com.mathvision.diet.repository.DishRepository; |
||||
|
import com.mathvision.diet.repository.MenuRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Value; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class DemoEnvLimitService { |
||||
|
@Value(value = "${demo.is-demo:false}") |
||||
|
private boolean isDemo; |
||||
|
|
||||
|
@Value(value = "${demo.params.img-enable:false}") |
||||
|
private boolean imgEnable; |
||||
|
|
||||
|
@Value(value = "${demo.params.dish-num:10}") |
||||
|
private long dishNum; |
||||
|
|
||||
|
@Value(value = "${demo.params.menu-num:5}") |
||||
|
private long menuNum; |
||||
|
|
||||
|
@Value(value = "${demo.params.rate-block:true}") |
||||
|
private boolean rateBlock; |
||||
|
|
||||
|
@Value(value = "${demo.params.rate-limit:500}") |
||||
|
private int rateLimit; |
||||
|
|
||||
|
private static RateLimiter apiRateLimiter; |
||||
|
|
||||
|
@Resource |
||||
|
private DishRepository dishRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuRepository menuRepository; |
||||
|
|
||||
|
@PostConstruct |
||||
|
public void init() { |
||||
|
if (isDemo) apiRateLimiter = RateLimiter.create(rateLimit, 10, TimeUnit.SECONDS); |
||||
|
} |
||||
|
|
||||
|
public boolean checkImgEnable() { |
||||
|
return isDemo ? imgEnable : true; |
||||
|
} |
||||
|
|
||||
|
public boolean checkDishNum(Long vendor) { |
||||
|
return !isDemo || dishRepository.countByVender(vendor) < dishNum; |
||||
|
} |
||||
|
|
||||
|
public boolean checkMenuNum(Long vendor) { |
||||
|
return !isDemo || menuRepository.countByVender(vendor) < menuNum; |
||||
|
} |
||||
|
|
||||
|
public boolean checkRateLimit() { |
||||
|
if (isDemo) { |
||||
|
if (rateBlock){ |
||||
|
apiRateLimiter.acquire(); |
||||
|
}else { |
||||
|
return apiRateLimiter.tryAcquire(); |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,297 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.google.common.collect.Lists; |
||||
|
import com.mathvision.diet.domain.ComponentAnalysisDO; |
||||
|
import com.mathvision.diet.domain.DishLabelDO; |
||||
|
import com.mathvision.diet.domian.DishItemDTO; |
||||
|
import com.mathvision.diet.entity.Dish; |
||||
|
import com.mathvision.diet.entity.FoodNutrient; |
||||
|
import com.mathvision.diet.entity.Ingredient; |
||||
|
import com.mathvision.diet.repository.DishRepository; |
||||
|
import com.mathvision.diet.repository.MenuDishRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.lang3.BooleanUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.jpa.domain.Specification; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import javax.persistence.criteria.Predicate; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.math.RoundingMode; |
||||
|
import java.text.DecimalFormat; |
||||
|
import java.time.Instant; |
||||
|
import java.util.*; |
||||
|
import java.util.concurrent.locks.Lock; |
||||
|
import java.util.concurrent.locks.ReentrantLock; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class DishService { |
||||
|
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 Lock UPDATE_LABEL_LOCK = new ReentrantLock(); |
||||
|
private static Instant UPDATE_LABEL_TIME; |
||||
|
|
||||
|
@Resource |
||||
|
private EnumService enumService; |
||||
|
|
||||
|
@Resource |
||||
|
private IngredientService ingredientService; |
||||
|
|
||||
|
@Resource |
||||
|
private DishRepository dishRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuDishRepository menuDishRepository; |
||||
|
|
||||
|
@Scheduled(cron = "0/2 * * * * *") |
||||
|
public void init() { |
||||
|
if (!UPDATE_LABEL_LOCK.tryLock()) { |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
List<Dish> dishes = UPDATE_LABEL_TIME == null ? dishRepository.findAll() : dishRepository.findByModifyGreaterThan(UPDATE_LABEL_TIME.minusMillis(1000)); |
||||
|
if (dishes.isEmpty()) { |
||||
|
return; |
||||
|
} |
||||
|
UPDATE_LABEL_TIME = Instant.now(); |
||||
|
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_LOCK.unlock(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Dish copy(Long id, Long vender, String operator, Instant instant) { |
||||
|
Dish dish = get(id); |
||||
|
List<Dish> dishes = dishRepository.findByVenderAndName(vender, dish.getName()); |
||||
|
if (CollectionUtils.isNotEmpty(dishes)) { |
||||
|
return dishes.get(0); |
||||
|
} |
||||
|
dish = dishRepository.save(Dish.builder().name(dish.getName()).vender(vender).marks(dish.getMarks()).label(dish.getLabel()).poly(dish.getPoly()).month(dish.getMonth()).icon(dish.getIcon()).ingredient(dish.getIngredient()).operate(operator).created(instant).modify(instant).build()); |
||||
|
log.info("[DishService] copy dish name = {}, operator = {}", dish.getName(), operator); |
||||
|
return dish; |
||||
|
} |
||||
|
|
||||
|
public void copy(Dish dish, List<Long> vendors, String operator) { |
||||
|
Instant instant = Instant.now(); |
||||
|
List<Dish> dishes = vendors.stream().filter(vender -> notExists(null, dish.getName(), vender)).map(vender -> Dish.builder().name(dish.getName()).vender(vender).marks(dish.getMarks()).poly(dish.getPoly()).label(dish.getLabel()).month(dish.getMonth()).icon(dish.getIcon()).ingredient(dish.getIngredient()).operate(operator).created(instant).modify(instant).build()).collect(Collectors.toList()); |
||||
|
dishRepository.saveAll(dishes); |
||||
|
log.info("[DishService] copy dishes count = {}, operator = {}", dishes.size(), operator); |
||||
|
} |
||||
|
|
||||
|
public void add(List<Dish> dishes, String operator) { |
||||
|
dishRepository.saveAll(dishes); |
||||
|
log.info("[DishService] add dishes count = {}, operator = {}", dishes.size(), operator); |
||||
|
} |
||||
|
|
||||
|
public void delete(List<Long> ids, Long venderId, String operator) { |
||||
|
if (venderId > 0) { |
||||
|
dishRepository.deleteByIdInAndVender(ids, venderId); |
||||
|
//食谱菜品空数据优化
|
||||
|
menuDishRepository.deleteByDishInAndVender(ids, venderId); |
||||
|
} else { |
||||
|
dishRepository.deleteAllByIdInBatch(ids); |
||||
|
menuDishRepository.deleteByDishIn(ids); |
||||
|
} |
||||
|
log.info("[DishService] delete ids = {}, operator = {}", ids, operator); |
||||
|
} |
||||
|
|
||||
|
public void delete(Long venderId, String operator) { |
||||
|
dishRepository.deleteByVender(venderId); |
||||
|
log.info("[DishService] delete venderId = {}, operator = {}", venderId, operator); |
||||
|
} |
||||
|
|
||||
|
public void update(Dish dish, String operator) { |
||||
|
dish.setModify(Instant.now()); |
||||
|
dishRepository.save(dish); |
||||
|
log.info("[DishService] update name = {}, operator = {}", dish.getName(), operator); |
||||
|
} |
||||
|
|
||||
|
public boolean exists(Long vender, List<Long> ids) { |
||||
|
return dishRepository.existsByVenderAndIdIn(vender, ids); |
||||
|
} |
||||
|
|
||||
|
public boolean notExists(Long id, String name, Long vender) { |
||||
|
return id == null ? !dishRepository.existsByVenderAndName(vender, name) : !dishRepository.existsByVenderAndNameAndIdNot(vender, name, id); |
||||
|
} |
||||
|
|
||||
|
public Dish get(Long id) { |
||||
|
return dishRepository.findById(id).orElse(null); |
||||
|
} |
||||
|
|
||||
|
public Dish get(Long id, Long vender) { |
||||
|
return dishRepository.findByIdAndVender(id, vender); |
||||
|
} |
||||
|
|
||||
|
public List<Dish> query(String keyword) { |
||||
|
return dishRepository.findByNameLikeOrderByIdDesc("%" + keyword + "%"); |
||||
|
} |
||||
|
|
||||
|
public Page<Dish> list(Long vender, String name, String mark, String poly, String label, PageRequest pageRequest) { |
||||
|
return dishRepository.findAll(toSpecification(vender, name, mark, poly, label), pageRequest); |
||||
|
} |
||||
|
|
||||
|
private Specification<Dish> toSpecification(Long vender, String name, String mark, String poly, String label) { |
||||
|
return (root, query, builder) -> { |
||||
|
List<Predicate> predicates = new ArrayList<>(); |
||||
|
|
||||
|
if (vender > 0) { |
||||
|
predicates.add(builder.equal(root.get("vender"), vender)); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isNotBlank(mark)) { |
||||
|
predicates.add(builder.equal(root.get("marks"), mark)); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isNotBlank(poly)) { |
||||
|
predicates.add(builder.equal(root.get("poly"), poly)); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isNotBlank(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) { |
||||
|
return builder.and(predicates.toArray(new Predicate[0])); |
||||
|
} else if (predicates.size() == 1) { |
||||
|
return predicates.get(0); |
||||
|
} else { |
||||
|
return null; |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public List<DishLabelDO> label(List<Long> ids, Long vender) { |
||||
|
List<Dish> dishes = Lists.newArrayList(); |
||||
|
if (CollectionUtils.isNotEmpty(ids)) { |
||||
|
if (vender > 0) { |
||||
|
dishes.addAll(dishRepository.findByVenderAndIdIn(vender, ids)); |
||||
|
} else { |
||||
|
dishes.addAll(dishRepository.findByIdIn(ids)); |
||||
|
} |
||||
|
} else { |
||||
|
if (vender > 0) { |
||||
|
dishes.addAll(dishRepository.findByVender(vender)); |
||||
|
} else { |
||||
|
dishes.addAll(dishRepository.findAll()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (dishes.isEmpty()) { |
||||
|
return Lists.newArrayList(); |
||||
|
} |
||||
|
|
||||
|
DecimalFormat formatInteger = new DecimalFormat(); |
||||
|
formatInteger.setMaximumFractionDigits(0); |
||||
|
formatInteger.setMinimumFractionDigits(0); |
||||
|
formatInteger.setRoundingMode(RoundingMode.HALF_UP); |
||||
|
|
||||
|
DecimalFormat formatValue = new DecimalFormat(); |
||||
|
formatValue.setMaximumFractionDigits(1); |
||||
|
formatValue.setMinimumFractionDigits(1); |
||||
|
formatValue.setRoundingMode(RoundingMode.HALF_UP); |
||||
|
|
||||
|
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)); |
||||
|
return dishes.parallelStream().filter(dish -> CollectionUtils.isNotEmpty(dish.getIngredient())).map(dish -> { |
||||
|
List<String> 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<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))) |
||||
|
).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 -> { |
||||
|
if (!_items.containsKey(x)) { |
||||
|
_items.put(x, BigDecimal.ZERO); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
Map<String, BigDecimal> 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(); |
||||
|
} |
||||
|
})); |
||||
|
|
||||
|
List<ComponentAnalysisDO> component = items.entrySet().stream().filter(x -> MUST_DISPLAY_ITEM.contains(x.getKey()) || WANT_DISPLAY_ITEM.contains(x.getKey()) && x.getValue() != null && x.getValue().compareTo(BigDecimal.ZERO) > 0).map(x -> { |
||||
|
FoodNutrient foodNutrient = enumService.getNutrient(x.getKey()); |
||||
|
if (foodNutrient == null) { |
||||
|
if (x.getKey().equals("sugar")) { |
||||
|
foodNutrient = FoodNutrient.builder().key(x.getKey()).value("糖").measurement("g").build(); |
||||
|
} else { |
||||
|
foodNutrient = FoodNutrient.builder().key(x.getKey()).value(x.getKey()).measurement("-").build(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
String name = foodNutrient.getValue(); |
||||
|
//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(); |
||||
|
name = "钠/食盐"; |
||||
|
value = String.format("%s(mg)/%s(g)", formatInteger.format(x.getValue().floatValue()), formatValue.format(salt)); |
||||
|
} |
||||
|
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).label(dish.getLabel()).build(); |
||||
|
}).collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
private BigDecimal sugar(Dish dish, Map<String, Ingredient> ingredientMap) { |
||||
|
BigDecimal total = dish.getIngredient().stream().map(DishItemDTO::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); |
||||
|
BigDecimal sugar = 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); |
||||
|
// 计算每100克食材中糖的含量
|
||||
|
if (total.compareTo(BigDecimal.ZERO) == 0) { |
||||
|
return BigDecimal.ZERO; |
||||
|
} |
||||
|
return sugar.divide(total, 4, RoundingMode.HALF_UP) |
||||
|
.multiply(new BigDecimal("100")) |
||||
|
.setScale(1, RoundingMode.HALF_UP); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,153 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.google.common.collect.Sets; |
||||
|
import com.mathvision.diet.domian.*; |
||||
|
import com.mathvision.diet.entity.*; |
||||
|
import com.mathvision.diet.repository.*; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.KeyValue; |
||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import java.util.*; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class EnumService { |
||||
|
private final FoodPolyRepository foodPolyRepository; |
||||
|
|
||||
|
public EnumService(FoodPolyRepository foodPolyRepository) { |
||||
|
this.foodPolyRepository = foodPolyRepository; |
||||
|
} |
||||
|
|
||||
|
private static Map<AuthType, Set<String>> AUTH_ITEMS = new HashMap<>(); |
||||
|
private static Map<Long, RoleItem> ROLE_ITEMS = new HashMap<>(); |
||||
|
private static Map<String, FoodMark> FOOD_MARK = new HashMap<>(); |
||||
|
private static Map<String, FoodPoly> FOOD_POLY = new HashMap<>(); |
||||
|
private static Map<String, FoodCategory> FOOD_CATEGORY = new HashMap<>(); |
||||
|
private static Map<String, FoodNutrient> FOOD_NUTRIENT = new HashMap<>(); |
||||
|
|
||||
|
@Resource |
||||
|
private RoleItemRepository roleItemRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private FoodMarkRepository foodMarkRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private FoodCategoryRepository foodCategoryRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private FoodNutrientRepository foodNutrientRepository; |
||||
|
|
||||
|
@PostConstruct |
||||
|
@Scheduled(cron = "0 0/5 * * * *") |
||||
|
public void init() { |
||||
|
ROLE_ITEMS = roleItemRepository.findAll().stream().collect(Collectors.toConcurrentMap(RoleItem::getId, x -> x)); |
||||
|
AUTH_ITEMS = ROLE_ITEMS.values().stream().map(item -> Pair.of(item.getItemType(), "/api/" + item.getItemValue().split(":", 2)[1])).collect(Collectors.toMap(Pair::getKey, v-> Sets.newHashSet(v.getValue()), Sets::union)); |
||||
|
FOOD_MARK = foodMarkRepository.findAll().stream().collect(Collectors.toConcurrentMap(FoodMark::getKey, x -> x)); |
||||
|
FOOD_POLY = foodPolyRepository.findAll().stream().collect(Collectors.toConcurrentMap(FoodPoly::getKey, x -> x)); |
||||
|
FOOD_CATEGORY = foodCategoryRepository.findAll().stream().collect(Collectors.toConcurrentMap(FoodCategory::getKey, x -> x)); |
||||
|
FOOD_NUTRIENT = foodNutrientRepository.findAll().stream().collect(Collectors.toConcurrentMap(FoodNutrient::getKey, x -> x)); |
||||
|
} |
||||
|
|
||||
|
public Map<String, Collection<?>> getAll() { |
||||
|
Map<String, Collection<?>> result = new HashMap<>(); |
||||
|
result.put("mark", FOOD_MARK.values()); |
||||
|
result.put("poly", FOOD_POLY.values()); |
||||
|
result.put("category", FOOD_CATEGORY.values()); |
||||
|
result.put("nutrient", FOOD_NUTRIENT.values()); |
||||
|
result.put("venderType", Arrays.stream(VenderType.values()).map(x -> new KeyValue<String, String>() { |
||||
|
@Override |
||||
|
public String getKey() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getValue() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
}).collect(Collectors.toList())); |
||||
|
result.put("markType", Arrays.stream(MarkType.values()).map(x -> new KeyValue<String, String>() { |
||||
|
@Override |
||||
|
public String getKey() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getValue() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
}).collect(Collectors.toList())); |
||||
|
result.put("mealType", Arrays.stream(MealType.values()).map(x -> new KeyValue<String, String>() { |
||||
|
@Override |
||||
|
public String getKey() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getValue() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
}).collect(Collectors.toList())); |
||||
|
result.put("menuStatus", Arrays.stream(MenuStatus.values()).map(x -> new KeyValue<Integer, String>() { |
||||
|
@Override |
||||
|
public Integer getKey() { |
||||
|
return x.getCode(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getValue() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
}).collect(Collectors.toList())); |
||||
|
result.put("measurementType", Arrays.stream(MeasurementType.values()).map(x -> new KeyValue<String, String>() { |
||||
|
@Override |
||||
|
public String getKey() { |
||||
|
return x.name(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String getValue() { |
||||
|
return x.getType(); |
||||
|
} |
||||
|
}).collect(Collectors.toList())); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public Set<String> getAuthItems(AuthType authType) { |
||||
|
return AUTH_ITEMS.getOrDefault(authType, Sets.newHashSet()); |
||||
|
} |
||||
|
|
||||
|
public List<RoleItem> getRoleItems(AuthType itemType) { |
||||
|
return ROLE_ITEMS.values().stream().filter(item -> item.getItemType().equals(itemType)).collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
public List<RoleItem> getRoleItems(List<Long> items) { |
||||
|
return ROLE_ITEMS.entrySet().stream().filter(x -> items.contains(x.getKey())).map(Map.Entry::getValue).collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
public boolean checkMark(String mark) { |
||||
|
return FOOD_MARK.containsKey(mark); |
||||
|
} |
||||
|
|
||||
|
public boolean checkPoly(String poly) { |
||||
|
return FOOD_POLY.containsKey(poly); |
||||
|
} |
||||
|
|
||||
|
public boolean checkCategory(String category) { |
||||
|
return FOOD_CATEGORY.containsKey(category); |
||||
|
} |
||||
|
|
||||
|
public boolean checkNutrient(String nutrient) { |
||||
|
return FOOD_NUTRIENT.containsKey(nutrient); |
||||
|
} |
||||
|
|
||||
|
public FoodNutrient getNutrient(String nutrient) { |
||||
|
return FOOD_NUTRIENT.get(nutrient); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,244 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.alibaba.excel.EasyExcel; |
||||
|
import com.alibaba.excel.context.AnalysisContext; |
||||
|
import com.alibaba.excel.read.listener.ReadListener; |
||||
|
import com.alibaba.excel.support.ExcelTypeEnum; |
||||
|
import com.alibaba.excel.write.metadata.style.WriteCellStyle; |
||||
|
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; |
||||
|
import com.google.common.collect.Lists; |
||||
|
import com.mathvision.diet.domian.MarkType; |
||||
|
import com.mathvision.diet.entity.Ingredient; |
||||
|
import com.mathvision.diet.entity.IngredientMark; |
||||
|
import com.mathvision.diet.excel.IngredientModel; |
||||
|
import com.mathvision.diet.excel.ResultModel; |
||||
|
import com.mathvision.diet.repository.IngredientDTORepository; |
||||
|
import com.mathvision.diet.repository.IngredientMarkRepository; |
||||
|
import com.mathvision.diet.repository.IngredientRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.MapUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||
|
import org.apache.poi.ss.usermodel.FillPatternType; |
||||
|
import org.apache.poi.ss.usermodel.IndexedColors; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
import org.springframework.util.Assert; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.io.InputStream; |
||||
|
import java.io.OutputStream; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
import java.util.Arrays; |
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class IngredientService { |
||||
|
|
||||
|
@Resource |
||||
|
private EnumService enumService; |
||||
|
|
||||
|
@Resource |
||||
|
private IngredientRepository ingredientRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private IngredientDTORepository ingredientDTORepository; |
||||
|
|
||||
|
@Resource |
||||
|
private IngredientMarkRepository ingredientMarkRepository; |
||||
|
|
||||
|
public void template(OutputStream outputStream) { |
||||
|
WriteCellStyle headWriteCellStyle = new WriteCellStyle(); |
||||
|
headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); |
||||
|
headWriteCellStyle.setFillForegroundColor(IndexedColors.PALE_BLUE.getIndex()); |
||||
|
|
||||
|
EasyExcel.write(outputStream).registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, new WriteCellStyle())) |
||||
|
.head(IngredientModel.class).excelType(ExcelTypeEnum.XLSX).sheet("食材导入模板").doWrite(Lists.newArrayList()); |
||||
|
} |
||||
|
|
||||
|
public void upload(InputStream inputStream, OutputStream outputStream, String operator) { |
||||
|
Instant dateTime = Instant.now(); |
||||
|
EasyExcel.read(inputStream, IngredientModel.class, new ReadListener<IngredientModel>() { |
||||
|
final List<ResultModel> resultModels = Lists.newArrayList(); |
||||
|
final List<Ingredient> ingredients = Lists.newArrayList(); |
||||
|
final Map<String, String> allItems = getByKeys(); |
||||
|
|
||||
|
@Override |
||||
|
public void onException(Exception exception, AnalysisContext context) { |
||||
|
if (exception != null) { |
||||
|
throw new IllegalArgumentException("导入异常:" + exception.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void invoke(IngredientModel o, AnalysisContext analysisContext) { |
||||
|
String resultKey = String.format("%s-%s-%s", o.getKey(), o.getName(), o.getType()); |
||||
|
|
||||
|
try { |
||||
|
Ingredient ingredient = Ingredient.builder().key(o.getKey()).name(o.getName()).type(o.getType()).nutrient(Arrays.stream(IngredientModel.class.getDeclaredFields()).filter(x -> BigDecimal.class.equals(x.getType())).peek(x -> x.setAccessible(true)).map(x -> { |
||||
|
try { |
||||
|
return Pair.of(x.getName(), (BigDecimal)x.get(o)); |
||||
|
} catch (IllegalAccessException e) { |
||||
|
throw new RuntimeException(e); |
||||
|
} |
||||
|
}).filter(x -> x.getValue() != null).collect(Collectors.toMap(Pair::getKey, Pair::getValue))).operate(operator).created(dateTime).modify(dateTime).build(); |
||||
|
|
||||
|
if (StringUtils.isBlank(ingredient.getKey())) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("食物编码为空").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (StringUtils.isBlank(ingredient.getName())) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("食物名称为空").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (allItems.containsKey(ingredient.getKey()) || allItems.containsValue(ingredient.getName())) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("编号/名称已存在").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (ingredients.stream().anyMatch(x -> x.getKey().equals(ingredient.getKey()))) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("编号在excel文件中存在重复").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (StringUtils.isBlank(ingredient.getType()) || !enumService.checkCategory(ingredient.getType())) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("食物类型为空或者不支持").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (MapUtils.isEmpty(ingredient.getNutrient())) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("营养素内容全空").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (ingredient.getNutrient().entrySet().stream().anyMatch(x -> !enumService.checkNutrient(x.getKey()))) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("包含不支持的营养素").build()); |
||||
|
return; |
||||
|
} |
||||
|
if (ingredient.getNutrient().entrySet().stream().anyMatch(x -> x.getValue().floatValue() < 0)) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("营养素含量不能识别").build()); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
ingredients.add(ingredient); |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("导入结果").build()); |
||||
|
} catch (Exception e) { |
||||
|
resultModels.add(ResultModel.builder().key(resultKey).result("导入失败:" + e.getMessage()).build()); |
||||
|
log.error(String.format("%s-%s-%s 导入失败: %s", o.getKey(), o.getName(), o.getType(), e.getMessage()), e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void doAfterAllAnalysed(AnalysisContext analysisContext) { |
||||
|
if (!ingredients.isEmpty()) { |
||||
|
ingredientRepository.saveAll(ingredients); |
||||
|
} |
||||
|
EasyExcel.write(outputStream).head(ResultModel.class).excelType(ExcelTypeEnum.XLSX).sheet("导入结果").doWrite(resultModels); |
||||
|
} |
||||
|
}).sheet().doRead(); |
||||
|
} |
||||
|
|
||||
|
public void addIngredient(Ingredient ingredient, String operator) { |
||||
|
Assert.isTrue(StringUtils.isNotBlank(ingredient.getKey()) && |
||||
|
StringUtils.isNotBlank(ingredient.getName()) && |
||||
|
StringUtils.isNotBlank(ingredient.getType()) && |
||||
|
MapUtils.isNotEmpty(ingredient.getNutrient()) && |
||||
|
enumService.checkCategory(ingredient.getType()) && |
||||
|
ingredient.getNutrient().entrySet().stream().allMatch(x -> enumService.checkNutrient(x.getKey())) && |
||||
|
!ingredientRepository.existsByKeyOrName(ingredient.getKey(), ingredient.getName()), |
||||
|
"[参数错误]必填参数未填写,或者编号名称重复、类型和营养素不在取值范围内!"); |
||||
|
|
||||
|
Instant dateTime = Instant.now(); |
||||
|
ingredient.setOperate(operator); |
||||
|
ingredient.setCreated(dateTime); |
||||
|
ingredient.setModify(dateTime); |
||||
|
ingredientRepository.save(ingredient); |
||||
|
log.info("[IngredientService] addIngredient name = " + ingredient.getName() + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public void delIngredient(List<String> ingredients, String operator) { |
||||
|
ingredients.stream().filter(StringUtils::isNotBlank).forEach(ingredient -> { |
||||
|
ingredientRepository.deleteByKey(ingredient); |
||||
|
ingredientMarkRepository.deleteByIngredient(ingredient); |
||||
|
log.info("[IngredientService] delIngredient ingredient = " + ingredient + ", operator = " + operator); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public void modIngredient(Ingredient ingredient, String operator) { |
||||
|
Assert.isTrue(StringUtils.isNotBlank(ingredient.getKey()) && |
||||
|
StringUtils.isNotBlank(ingredient.getName()) && |
||||
|
StringUtils.isNotBlank(ingredient.getType()) && |
||||
|
MapUtils.isNotEmpty(ingredient.getNutrient()) && |
||||
|
enumService.checkCategory(ingredient.getType()) && |
||||
|
ingredient.getNutrient().entrySet().stream().allMatch(x -> enumService.checkNutrient(x.getKey())) && |
||||
|
!ingredientRepository.existsByIdNotAndKeyOrName(ingredient.getId(), ingredient.getKey(), ingredient.getName()), |
||||
|
"[参数错误]必填参数未填写,或者编号名称重复、类型和营养素不在取值范围内!"); |
||||
|
Instant dateTime = Instant.now(); |
||||
|
ingredient.setOperate(operator); |
||||
|
ingredient.setCreated(dateTime); |
||||
|
ingredient.setModify(dateTime); |
||||
|
ingredientRepository.save(ingredient); |
||||
|
log.info("[IngredientService] modIngredient name = " + ingredient.getName() + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public Map<String, String> getByKeys() { |
||||
|
return ingredientRepository.findKeyNameMap().stream().collect(Collectors.toMap(Ingredient::getKey, Ingredient::getName)); |
||||
|
} |
||||
|
|
||||
|
public List<Ingredient> getByKeys(List<String> keys) { |
||||
|
return ingredientRepository.findByKeyInOrderByKeyAsc(keys); |
||||
|
} |
||||
|
|
||||
|
public List<Ingredient> getByKeyword(String keyword) { |
||||
|
return ingredientRepository.findByKeyLikeOrNameLikeOrderByKeyAsc(keyword); |
||||
|
} |
||||
|
|
||||
|
public List<Ingredient> getFullByKeys(Collection<String> keys) { |
||||
|
return ingredientRepository.findByKeyIn(keys); |
||||
|
} |
||||
|
|
||||
|
public Page<?> queryIngredientByMark(Long vender, String mark, String key, String type, PageRequest pageRequest) { |
||||
|
if (vender <= 0) { |
||||
|
if (StringUtils.isBlank(key)) { |
||||
|
return StringUtils.isBlank(type) ? ingredientRepository.findAll(pageRequest) : ingredientRepository.findByTypeOrderByIdDesc(type, pageRequest); |
||||
|
} |
||||
|
if (StringUtils.isNumeric(key)) { |
||||
|
return StringUtils.isBlank(type) ? ingredientRepository.findByKeyLikeOrderByIdDesc("%" + key + "%", pageRequest) : ingredientRepository.findByTypeAndKeyLikeOrderByIdDesc(type, "%" + key + "%", pageRequest); |
||||
|
} else { |
||||
|
return StringUtils.isBlank(type) ? ingredientRepository.findByNameLikeOrderByIdDesc("%" + key + "%", pageRequest) : ingredientRepository.findByTypeAndNameLikeOrderByIdDesc(type, "%" + key + "%", pageRequest); |
||||
|
} |
||||
|
} else { |
||||
|
return ingredientDTORepository.findByVenderAndTypeAndMarkAndKey(vender, type, mark, key, pageRequest); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Ingredient queryIngredientByKey(String key) { |
||||
|
return ingredientRepository.findByKey(key); |
||||
|
} |
||||
|
|
||||
|
public boolean existsIngredientByKey(String key) { |
||||
|
return ingredientRepository.existsByKey(key); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void addMark(MarkType mark, String ingredient, Long vender, String operator) { |
||||
|
if (ingredientMarkRepository.updateMarkAndOperateByVenderAndIngredient(mark, operator, vender, ingredient) <= 0) { |
||||
|
Instant dateTime = Instant.now(); |
||||
|
ingredientMarkRepository.save(IngredientMark.builder().mark(mark).ingredient(ingredient).vender(vender).operate(operator).created(dateTime).modify(dateTime).build()); |
||||
|
} |
||||
|
log.info("[IngredientService] addMark ingredient = " + ingredient + ", mark = " + mark + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public void delMark(String ingredient, Long vender, String operator) { |
||||
|
ingredientMarkRepository.deleteByVenderAndIngredient(vender, ingredient); |
||||
|
log.info("[IngredientService] delMark ingredient = " + ingredient + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public void delMark(Long vender, String operator) { |
||||
|
ingredientMarkRepository.deleteByVender(vender); |
||||
|
log.info("[IngredientService] delMark vender = " + vender + ", operator = " + operator); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,273 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.alibaba.excel.EasyExcel; |
||||
|
import com.alibaba.excel.ExcelWriter; |
||||
|
import com.deepoove.poi.XWPFTemplate; |
||||
|
import com.deepoove.poi.config.Configure; |
||||
|
import com.deepoove.poi.config.ConfigureBuilder; |
||||
|
import com.deepoove.poi.data.RowRenderData; |
||||
|
import com.deepoove.poi.data.Rows; |
||||
|
import com.google.common.collect.Lists; |
||||
|
import com.google.common.collect.Maps; |
||||
|
import com.mathvision.diet.domian.MealType; |
||||
|
import com.mathvision.diet.domian.MenuDishItemDTO; |
||||
|
import com.mathvision.diet.entity.Dish; |
||||
|
import com.mathvision.diet.entity.Menu; |
||||
|
import com.mathvision.diet.entity.MenuDish; |
||||
|
import com.mathvision.diet.repository.DishRepository; |
||||
|
import com.mathvision.diet.repository.MenuDishRepository; |
||||
|
import com.mathvision.diet.word.ServerTableData; |
||||
|
import com.mathvision.diet.word.ServerTablePolicy; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.io.*; |
||||
|
import java.math.RoundingMode; |
||||
|
import java.nio.file.Files; |
||||
|
import java.nio.file.Path; |
||||
|
import java.nio.file.Paths; |
||||
|
import java.time.Instant; |
||||
|
import java.util.*; |
||||
|
import java.util.concurrent.locks.Lock; |
||||
|
import java.util.concurrent.locks.ReentrantLock; |
||||
|
import java.util.stream.Collectors; |
||||
|
import java.util.stream.IntStream; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class MenuDishService { |
||||
|
private static final Lock UPDATE_LABEL_LOCK = new ReentrantLock(); |
||||
|
private static Instant UPDATE_LABEL_TIME; |
||||
|
|
||||
|
@Resource |
||||
|
DishRepository dishRepository; |
||||
|
|
||||
|
@Resource |
||||
|
MenuDishRepository menuDishRepository; |
||||
|
|
||||
|
@Resource |
||||
|
IngredientService ingredientService; |
||||
|
|
||||
|
@Scheduled(cron = "0/5 * * * * *") |
||||
|
public void init() { |
||||
|
if (!UPDATE_LABEL_LOCK.tryLock()) { |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
List<MenuDish> dishes = UPDATE_LABEL_TIME == null ? menuDishRepository.findAll() : menuDishRepository.findByModifyGreaterThan(UPDATE_LABEL_TIME.minusMillis(1000)); |
||||
|
if (dishes.isEmpty()) { |
||||
|
return; |
||||
|
} |
||||
|
UPDATE_LABEL_TIME = Instant.now(); |
||||
|
dishes.forEach(menuDish -> { |
||||
|
Dish dish = dishRepository.findByIdAndVender(menuDish.getDish(), menuDish.getVender()); |
||||
|
if (dish != null && dish.getLabel() != null) { |
||||
|
menuDish.setLabel(dish.getLabel()); |
||||
|
} |
||||
|
}); |
||||
|
menuDishRepository.saveAll(dishes); |
||||
|
} catch (Exception e) { |
||||
|
log.error("[MenuDishService] update label exception : " + e.getMessage(), e); |
||||
|
} finally { |
||||
|
UPDATE_LABEL_LOCK.unlock(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public MenuDish add(MenuDish menuDish) { |
||||
|
return menuDishRepository.save(menuDish); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public List<MenuDish> addAll(List<MenuDish> menuDishes) { |
||||
|
menuDishes.forEach(menuDish -> deleteAll(menuDish.getMenu())); |
||||
|
return menuDishRepository.saveAll(menuDishes); |
||||
|
} |
||||
|
|
||||
|
public void deleteAll(Long menuId) { |
||||
|
menuDishRepository.deleteByMenu(menuId); |
||||
|
} |
||||
|
|
||||
|
public void delete(Long menuDishId) { |
||||
|
menuDishRepository.deleteById(menuDishId); |
||||
|
} |
||||
|
|
||||
|
public MenuDish get(Long id) { |
||||
|
return menuDishRepository.findById(id).orElse(null); |
||||
|
} |
||||
|
|
||||
|
public MenuDish get(Long id, Long venderId) { |
||||
|
return menuDishRepository.findByIdAndVender(id, venderId); |
||||
|
} |
||||
|
|
||||
|
public List<MenuDish> query(Long menuId) { |
||||
|
return menuDishRepository.findByMenu(menuId); |
||||
|
} |
||||
|
|
||||
|
public List<MenuDish> query(Long menuId, Long vender) { |
||||
|
return menuDishRepository.findByMenuAndVender(menuId, vender); |
||||
|
} |
||||
|
|
||||
|
public List<MenuDish> query(Long menuId, Long vender, Long day) { |
||||
|
return menuDishRepository.findByMenuAndVenderAndDay(menuId, vender, day); |
||||
|
} |
||||
|
|
||||
|
public List<Long> days(Long menuId, Long vender) { |
||||
|
return menuDishRepository.distinctDaysByMenuAndVender(menuId, vender); |
||||
|
} |
||||
|
|
||||
|
public void export(Menu menu, ExcelWriter excelWriter) { |
||||
|
Map<String, Map<Long, List<MenuDish>>> menuDishes = menuDishRepository.findByMenu(menu.getId()).stream().collect(Collectors.groupingBy(MenuDish::getMeal, Collectors.groupingBy(MenuDish::getDay))); |
||||
|
List<String> allMeals = new ArrayList<>(menuDishes.keySet()).stream().sorted(Comparator.comparing(MealType::toType)).collect(Collectors.toList()); |
||||
|
List<Long> allDays = menuDishes.entrySet().stream().flatMap(kv -> kv.getValue().keySet().stream()).distinct().sorted().collect(Collectors.toList()); |
||||
|
List<String> allCrows = menu.getCrows(); |
||||
|
if (CollectionUtils.isEmpty(allDays)) { |
||||
|
allDays = menu.getDay(); |
||||
|
} |
||||
|
|
||||
|
List<List<String>> headers = Lists.newArrayList(); |
||||
|
headers.add(Lists.newArrayList("")); |
||||
|
allDays.forEach(day -> { |
||||
|
headers.add(Lists.newArrayList(String.format("第%s天", day), "菜品名称")); |
||||
|
headers.add(Lists.newArrayList(String.format("第%s天", day), "食材名称")); |
||||
|
allCrows.forEach(crow -> headers.add(Lists.newArrayList(String.format("第%s天", day), crow))); |
||||
|
}); |
||||
|
|
||||
|
Map<String, String> keyName = ingredientService.getByKeys(); |
||||
|
List<List<Object>> contents = Lists.newArrayList(); |
||||
|
List<Long> finalAllDays = allDays; |
||||
|
allMeals.forEach(meal -> { |
||||
|
int maxDishes = menuDishes.get(meal).values().stream().map(List::size).max(Comparator.naturalOrder()).orElse(0); |
||||
|
if (maxDishes <= 0) return; |
||||
|
IntStream.rangeClosed(1, maxDishes).forEach(dishIndex -> { |
||||
|
List<MenuDish> dishes = finalAllDays.stream().map(day -> { |
||||
|
List<MenuDish> dish = menuDishes.get(meal).get(day); |
||||
|
if (dish == null || dish.size() < dishIndex) { |
||||
|
return MenuDish.builder().meal(meal).day(day).ingredient(Lists.newArrayList()).build(); |
||||
|
} else { |
||||
|
return dish.get(dishIndex - 1); |
||||
|
} |
||||
|
}).collect(Collectors.toList()); |
||||
|
|
||||
|
int maxItems = dishes.stream().map(item -> item.getIngredient().size()).max(Comparator.naturalOrder()).orElse(0); |
||||
|
if (maxItems <= 0) return; |
||||
|
IntStream.rangeClosed(1, maxItems).forEach(itemIndex -> { |
||||
|
List<Pair<String, MenuDishItemDTO>> items = dishes.stream().map(dish -> { |
||||
|
List<MenuDishItemDTO> item = dish.getIngredient(); |
||||
|
if (item == null || item.size() < itemIndex) { |
||||
|
return Pair.of("", MenuDishItemDTO.builder().value(Maps.newHashMap()).build()); |
||||
|
} else { |
||||
|
return Pair.of(dish.getName(), item.get(itemIndex - 1)); |
||||
|
} |
||||
|
}).collect(Collectors.toList()); |
||||
|
|
||||
|
List<Object> content = Lists.newArrayList(); |
||||
|
content.add(meal); |
||||
|
items.forEach(item -> { |
||||
|
content.add(item.getKey()); |
||||
|
content.add(keyName.getOrDefault(item.getValue().getKey(), item.getValue().getKey())); |
||||
|
allCrows.forEach(crow -> content.add(item.getValue().getValue().get(crow))); |
||||
|
}); |
||||
|
contents.add(content); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
excelWriter.write(contents, EasyExcel.writerSheet(menu.getName()).head(headers).build()); |
||||
|
} |
||||
|
|
||||
|
public byte[] exportWord(Menu menu) { |
||||
|
Map<String, Map<Long, List<MenuDish>>> menuDishes = Optional.ofNullable(menuDishRepository.findByMenu(menu.getId())).orElseGet(Collections::emptyList).stream().collect(Collectors.groupingBy(MenuDish::getMeal, Collectors.groupingBy(MenuDish::getDay))); |
||||
|
List<String> allMeals = menuDishes.keySet().stream().sorted(Comparator.comparing(MealType::toType)).collect(Collectors.toList()); |
||||
|
List<Long> allDays = menuDishes.values().stream().flatMap(dayMap -> dayMap.keySet().stream()).distinct().sorted().collect(Collectors.toList()); |
||||
|
|
||||
|
if (CollectionUtils.isEmpty(allDays)) { |
||||
|
allDays = Optional.ofNullable(menu.getDay()).orElseGet(Collections::emptyList); |
||||
|
} |
||||
|
|
||||
|
List<String> allCrows = Optional.ofNullable(menu.getCrows()).orElseGet(Collections::emptyList); |
||||
|
Map<String, String> ingredientKeyToName = ingredientService.getByKeys(); |
||||
|
List<Map<String, Object>> tableList = allDays.stream().map(day -> { |
||||
|
ServerTableData tableData = new ServerTableData(); |
||||
|
Map<String, Object> tableDataMap = new HashMap<>(); |
||||
|
tableDataMap.put("tableName", toWeekDay(day)); |
||||
|
|
||||
|
tableData.setExtendedColumn(allCrows); |
||||
|
List<RowRenderData> serverDataList = new ArrayList<>(); |
||||
|
|
||||
|
allMeals.forEach(meal -> { |
||||
|
Map<Long, List<MenuDish>> dayMap = menuDishes.get(meal); |
||||
|
if (dayMap == null) return; |
||||
|
|
||||
|
List<MenuDish> dishes = dayMap.get(day); |
||||
|
if (CollectionUtils.isEmpty(dishes)) return; |
||||
|
|
||||
|
dishes.forEach(dish -> { |
||||
|
List<MenuDishItemDTO> ingredients = dish.getIngredient(); |
||||
|
ingredients.forEach(item -> { |
||||
|
String[] content = new String[allCrows.size() + 2]; |
||||
|
content[0] = dish.getName(); |
||||
|
// 去掉[]里的内容
|
||||
|
content[1] = ingredientKeyToName.getOrDefault(item.getKey(), "").replaceAll("\\[.*?\\]", ""); |
||||
|
item.getValue().forEach((key, value) -> { |
||||
|
int index = allCrows.indexOf(key); |
||||
|
if (index >= 0 && index < allCrows.size()) { |
||||
|
// 保留一位小数
|
||||
|
content[index + 2] = value != null ? value.setScale(1, RoundingMode.HALF_UP).toString() : ""; |
||||
|
} |
||||
|
}); |
||||
|
serverDataList.add(Rows.of(content).center().create()); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
tableData.setServerDataList(serverDataList); |
||||
|
tableData.setMergeColumn(0); |
||||
|
tableDataMap.put("tableData", tableData); |
||||
|
return tableDataMap; |
||||
|
}).collect(Collectors.toList()); |
||||
|
|
||||
|
// Word生成阶段
|
||||
|
ConfigureBuilder builder = Configure.builder().useSpringEL(false); |
||||
|
Map<String, Object> dataMap = new HashMap<>(); |
||||
|
dataMap.put("title", menu.getName()); |
||||
|
dataMap.put("tableList", tableList); |
||||
|
builder.bind("tableData", new ServerTablePolicy()); |
||||
|
|
||||
|
Path templatePath = Paths.get("E:\\data\\diet.docx"); |
||||
|
|
||||
|
try (InputStream is = Files.newInputStream(templatePath); |
||||
|
ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) { |
||||
|
XWPFTemplate template = XWPFTemplate.compile(is, builder.build()).render(dataMap); |
||||
|
template.writeAndClose(byteOut); |
||||
|
return byteOut.toByteArray(); |
||||
|
} catch (Exception e) { |
||||
|
log.error("[MenuExport] Word导出失败", e); |
||||
|
throw new RuntimeException("文档生成失败", e); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private String toWeekDay(long day) { |
||||
|
switch ((int) day) { |
||||
|
case 1: |
||||
|
return "周一"; |
||||
|
case 2: |
||||
|
return "周二"; |
||||
|
case 3: |
||||
|
return "周三"; |
||||
|
case 4: |
||||
|
return "周四"; |
||||
|
case 5: |
||||
|
return "周五"; |
||||
|
case 6: |
||||
|
return "周六"; |
||||
|
case 7: |
||||
|
return "周日"; |
||||
|
default: |
||||
|
return ""; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,93 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.mathvision.diet.domian.MenuStatus; |
||||
|
import com.mathvision.diet.entity.Menu; |
||||
|
import com.mathvision.diet.repository.MenuDishRepository; |
||||
|
import com.mathvision.diet.repository.MenuRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.jpa.domain.Specification; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import javax.persistence.criteria.Predicate; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class MenuReleaseService { |
||||
|
|
||||
|
@Resource |
||||
|
private MenuRepository menuRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuDishRepository menuDishRepository; |
||||
|
|
||||
|
@PostConstruct |
||||
|
@Scheduled(cron = "0 0 0/6 * * *") |
||||
|
public void init() { |
||||
|
menuRepository.scanExpired(); |
||||
|
} |
||||
|
|
||||
|
public void publish(Long id, Map<String, Integer> scale, Date startTime, Date endTime, String operator) { |
||||
|
menuRepository.updateStatusAndScaleAndStartTimeAndEndTimeById(MenuStatus.publish, scale, startTime.toInstant(), endTime.toInstant(), id); |
||||
|
log.info("[MenuReleaseService] publish id = " + id + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public void cancel(Long id, String operator) { |
||||
|
menuRepository.updateStatusAndStartTimeAndEndTimeAndOperateById(MenuStatus.draft, null, null, operator, id); |
||||
|
log.info("[MenuReleaseService] cancel id = " + id + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public List<Menu> current(Long vender, Long day) { |
||||
|
List<Menu> result = menuRepository.findCurrentMenu(vender); |
||||
|
return result.parallelStream().filter(x -> menuDishRepository.existsByMenuAndDay(x.getId(), day)).collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
public List<Long> currentWeek(Long vender) { |
||||
|
List<Menu> result = menuRepository.findCurrentWeekMenu(vender); |
||||
|
return result.parallelStream().filter(x -> menuDishRepository.existsByMenu(x.getId())).map(Menu::getDay).flatMap(List::stream).distinct().collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
public Page<Menu> list(Long vender, String name, Date startTime, Date endTime, PageRequest pageRequest) { |
||||
|
return menuRepository.findAll(toSpecification(vender, name, startTime, endTime), pageRequest); |
||||
|
} |
||||
|
|
||||
|
private Specification<Menu> toSpecification(Long vender, String name, Date startTime, Date endTime) { |
||||
|
return (root, query, builder) -> { |
||||
|
List<Predicate> predicates = new ArrayList<>(); |
||||
|
|
||||
|
if (vender != null && vender > 0) { |
||||
|
predicates.add(builder.equal(root.get("vender"), vender)); |
||||
|
} |
||||
|
|
||||
|
predicates.add(builder.equal(root.get("status"), MenuStatus.publish)); |
||||
|
|
||||
|
if (startTime != null) { |
||||
|
predicates.add(builder.greaterThanOrEqualTo(root.get("modify"), startTime.toInstant())); |
||||
|
} |
||||
|
|
||||
|
if (endTime != null) { |
||||
|
predicates.add(builder.lessThanOrEqualTo(root.get("modify"), endTime.toInstant())); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isNotBlank(name)) { |
||||
|
predicates.add(builder.like(root.get("name"), "%" + name + "%")); |
||||
|
} |
||||
|
|
||||
|
if (predicates.size() > 1) { |
||||
|
return builder.and(predicates.toArray(new Predicate[0])); |
||||
|
} else { |
||||
|
return predicates.get(0); |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,447 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.alibaba.excel.EasyExcel; |
||||
|
import com.alibaba.excel.ExcelWriter; |
||||
|
import com.alibaba.fastjson2.JSONArray; |
||||
|
import com.alibaba.fastjson2.JSONObject; |
||||
|
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.*; |
||||
|
import com.mathvision.diet.entity.*; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.collections4.MapUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||
|
import org.apache.commons.lang3.tuple.Triple; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.math.RoundingMode; |
||||
|
import java.util.*; |
||||
|
import java.util.function.Function; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class MenuReportService { |
||||
|
@Resource |
||||
|
EnumService enumService; |
||||
|
|
||||
|
@Resource |
||||
|
NutritionService nutritionService; |
||||
|
|
||||
|
@Resource |
||||
|
MenuDishService menuDishService; |
||||
|
|
||||
|
@Resource |
||||
|
IngredientService ingredientService; |
||||
|
|
||||
|
@Resource |
||||
|
VenderService venderService; |
||||
|
|
||||
|
public JSONObject nutrition(Menu menu, long day, String crow) { |
||||
|
Nutrition nutrition = getNutrition(menu); |
||||
|
List<MenuDish> dishes = day == 0 ? menuDishService.query(menu.getId(), menu.getVender()) : menuDishService.query(menu.getId(), menu.getVender(), day); |
||||
|
Map<String, Map<String, BigDecimal>> itemStandard = nutrition.getIngredient().getOrDefault(crow, new HashMap<>()); |
||||
|
Map<String, Ingredient> 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<String, BigDecimal> items = dishes.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)))) |
||||
|
.collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); |
||||
|
//Map<String, Integer> 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<String, String> categoryType = new HashMap<>(); |
||||
|
nutrition.getFoodCategoryDay().forEach(foodCategoryDay -> foodCategoryDay.getCategory().forEach(category -> categoryType.put(category, foodCategoryDay.getName()))); |
||||
|
Map<String, Integer> 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)) { |
||||
|
items.put(key, BigDecimal.ZERO); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
JSONObject result = new JSONObject(); |
||||
|
result.put("day", day); |
||||
|
result.put("crow", crow); |
||||
|
result.put("meals", dishes.stream().map(MenuDish::getMeal).collect(Collectors.toSet())); |
||||
|
result.put("types", types); |
||||
|
if (day == 0) { |
||||
|
List<Long> days = dishes.stream().map(MenuDish::getDay).distinct().collect(Collectors.toList()); |
||||
|
if (CollectionUtils.isNotEmpty(days)) { |
||||
|
result.put("days", days); |
||||
|
items.forEach((k, v) -> items.put(k, v.divide(new BigDecimal(days.size()), RoundingMode.HALF_UP))); |
||||
|
} |
||||
|
} else { |
||||
|
List<Long> days = menuDishService.days(menu.getId(), menu.getVender()); |
||||
|
if (CollectionUtils.isNotEmpty(days)) { |
||||
|
result.put("days", days); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
JSONArray contents = new JSONArray(); |
||||
|
items.forEach((key, value) -> { |
||||
|
FoodNutrient foodNutrient = enumService.getNutrient(key); |
||||
|
BigDecimal overflow = MapUtils.isNotEmpty(nutrition.getOverflows()) ? nutrition.getOverflows().getOrDefault(key, nutrition.getOverflow()) : nutrition.getOverflow(); |
||||
|
|
||||
|
if (foodNutrient == null) { |
||||
|
return; |
||||
|
} |
||||
|
JSONObject content = new JSONObject(); |
||||
|
content.put("nutrition", String.format("%s/%s", foodNutrient.getValue(), foodNutrient.getMeasurement())); |
||||
|
content.put("virtual", "energy".equals(key) ? value.setScale(0, RoundingMode.HALF_UP) : value); |
||||
|
|
||||
|
Map<String, BigDecimal> standard = itemStandard.get(key); |
||||
|
BigDecimal max = standard == null ? null : standard.get("max"); |
||||
|
BigDecimal min = standard == null ? null : standard.get("min"); |
||||
|
BigDecimal ul = standard == null ? null : standard.get("ul"); |
||||
|
content.put("ul", ul == null ? "-" : ul.toString()); |
||||
|
|
||||
|
boolean byMax = false; |
||||
|
boolean byMin = false; |
||||
|
if (max == null || max.compareTo(BigDecimal.ZERO) == 0) { |
||||
|
if (min == null || min.compareTo(BigDecimal.ZERO) == 0) { |
||||
|
content.put("standard", "-"); |
||||
|
content.put("overload", "-"); |
||||
|
content.put("conclusion", "-"); |
||||
|
return; |
||||
|
} else { |
||||
|
content.put("standard", "≥" + min); |
||||
|
if (value.compareTo(min) >= 0) { |
||||
|
content.put("overload", "-"); |
||||
|
content.put("conclusion", "适量"); |
||||
|
} else { |
||||
|
byMin = true; |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
if (min == null || min.compareTo(BigDecimal.ZERO) == 0) { |
||||
|
content.put("standard", "≤" + max); |
||||
|
if (max.compareTo(value) >= 0) { |
||||
|
content.put("overload", "-"); |
||||
|
content.put("conclusion", "适量"); |
||||
|
} else { |
||||
|
byMax = true; |
||||
|
} |
||||
|
} else { |
||||
|
content.put("standard", min + "~" + max); |
||||
|
if (Range.closed(min, max).contains(value)) { |
||||
|
content.put("overload", "-"); |
||||
|
content.put("conclusion", "适量"); |
||||
|
} else { |
||||
|
if (value.compareTo(max) > 0) { |
||||
|
byMax = true; |
||||
|
} else { |
||||
|
byMin = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (byMin) { |
||||
|
BigDecimal overload = calculatePercentage(value, min); |
||||
|
content.put("overload", overload + "%"); |
||||
|
if (overload.abs().compareTo(overflow) > 0) { |
||||
|
content.put("conclusion", "不足"); |
||||
|
} else { |
||||
|
content.put("conclusion", "适量"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (byMax) { |
||||
|
BigDecimal overload = calculatePercentage(value, max); |
||||
|
content.put("overload", overload + "%"); |
||||
|
if (overload.compareTo(overflow) > 0) { |
||||
|
if (ul != null && value.compareTo(ul) > 0) { |
||||
|
content.put("conclusion", "严重超标"); |
||||
|
} else { |
||||
|
content.put("conclusion", "过量"); |
||||
|
} |
||||
|
} else { |
||||
|
content.put("conclusion", "适量"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
contents.add(content); |
||||
|
}); |
||||
|
|
||||
|
// update 按规则排序
|
||||
|
JSONArray sortContents = NutritionSortEnum.sortByRule(contents); |
||||
|
result.put("ingredient", sortContents); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public JSONObject types(Menu menu, String crow, List<MenuDish> dishes) { |
||||
|
dishes = dishes.stream().filter(menuDish -> menuDish.getIngredient().stream().anyMatch(item -> item.getValue().containsKey(crow))).collect(Collectors.toList()); |
||||
|
Nutrition nutrition = getNutrition(menu); |
||||
|
|
||||
|
List<RuleItemDTO> dayStandard = nutrition.getFoodCategoryDay(); |
||||
|
List<RuleItemDTO> weekStandard = nutrition.getFoodCategoryWeek(); |
||||
|
Map<String, Ingredient> 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<Pair<Long, String>, 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<Pair<Long, String>, 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<Pair<Long, String>, 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<Long, Object> dayRule = Maps.newHashMap(); |
||||
|
dishes.stream().map(MenuDish::getDay).forEach(day -> dayRule.put(day, dayStandard.stream().map(standard -> { |
||||
|
JSONObject content = new JSONObject(); |
||||
|
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()); |
||||
|
content.put("supplied", supplied); |
||||
|
content.put("lack", standard.getLack(new BigDecimal(supplied))); |
||||
|
} else { |
||||
|
BigDecimal supplied = weightDay.entrySet().stream().filter(x -> x.getKey().getKey().equals(day) && standard.getCategory().contains(x.getKey().getValue())).map(Map.Entry::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); |
||||
|
content.put("measurement", standard.getType()); |
||||
|
content.put("supplied", supplied); |
||||
|
content.put("lack", standard.getLack(supplied)); |
||||
|
} |
||||
|
return content; |
||||
|
}).collect(Collectors.toList()))); |
||||
|
|
||||
|
List<JSONObject> weekRule = weekStandard.stream().map(standard -> { |
||||
|
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()); |
||||
|
content.put("supplied", supplied); |
||||
|
content.put("lack", standard.getLack(new BigDecimal(supplied))); |
||||
|
} else { |
||||
|
BigDecimal supplied = weightDay.entrySet().stream().filter(x -> standard.getCategory().contains(x.getKey().getValue())).map(Map.Entry::getValue).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); |
||||
|
content.put("measurement", standard.getType()); |
||||
|
content.put("supplied", supplied); |
||||
|
content.put("lack", standard.getLack(supplied)); |
||||
|
} |
||||
|
return content; |
||||
|
}).collect(Collectors.toList()); |
||||
|
|
||||
|
JSONObject result = new JSONObject(); |
||||
|
result.put("crow", crow); |
||||
|
result.put("dayRule", dayRule); |
||||
|
result.put("weekRule", weekRule); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public JSONObject poly(String crow, List<MenuDish> dishes) { |
||||
|
dishes = dishes.stream().filter(menuDish -> menuDish.getIngredient().stream().anyMatch(item -> item.getValue().containsKey(crow))).collect(Collectors.toList()); |
||||
|
Map<String, List<MenuDish>> data = dishes.stream().collect(Collectors.groupingBy(MenuDish::getPoly)); |
||||
|
JSONObject result = new JSONObject(); |
||||
|
result.put("crow", crow); |
||||
|
result.put("0", data.entrySet().stream().map(x -> Pair.of(x.getKey(), x.getValue().size())).collect(Collectors.toMap(Pair::getKey, Pair::getValue))); |
||||
|
dishes.stream().collect(Collectors.groupingBy(MenuDish::getDay, Collectors.groupingBy(MenuDish::getPoly))).forEach((k, v) -> result.put(k.toString(), v.entrySet().stream().map(x -> Pair.of(x.getKey(), x.getValue().size())).collect(Collectors.toMap(Pair::getKey, Pair::getValue)))); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public JSONObject energy(long day, String crow, List<MenuDish> dishes) { |
||||
|
List<String> allConcerned = Lists.newArrayList("protein", "fat", "carbs"); |
||||
|
Map<String, Ingredient> 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<String, BigDecimal> items = dishes.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 -> allConcerned.contains(x.getKey())) |
||||
|
.collect(Collectors.toMap(Pair::getKey, Pair::getValue, BigDecimal::add)); |
||||
|
|
||||
|
allConcerned.forEach(key -> { |
||||
|
if (!items.containsKey(key)) { |
||||
|
items.put(key, BigDecimal.ZERO); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
JSONObject result = new JSONObject(); |
||||
|
result.put("day", day); |
||||
|
result.put("crow", crow); |
||||
|
result.put("meals", dishes.stream().map(MenuDish::getMeal).collect(Collectors.toSet())); |
||||
|
List<Long> days = dishes.stream().map(MenuDish::getDay).collect(Collectors.toList()); |
||||
|
if (CollectionUtils.isNotEmpty(days)) { |
||||
|
result.put("days", days); |
||||
|
if (day == 0) { |
||||
|
items.forEach((k, v) -> items.put(k, v.divide(new BigDecimal(days.size()), RoundingMode.HALF_UP))); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
BigDecimal protein = items.get("protein").multiply(new BigDecimal("4")); |
||||
|
BigDecimal fat = items.get("fat").multiply(new BigDecimal("9")); |
||||
|
BigDecimal carbs = items.get("carbs").multiply(new BigDecimal("4")); |
||||
|
BigDecimal total = protein.add(fat).add(carbs); |
||||
|
|
||||
|
JSONArray contents = new JSONArray(); |
||||
|
contents.add(toEnergyContent(total, "protein", protein, Range.closed(10, 20))); |
||||
|
contents.add(toEnergyContent(total, "fat", fat, Range.closed(20, 30))); |
||||
|
contents.add(toEnergyContent(total, "carbs", carbs, Range.closed(50, 60))); |
||||
|
result.put("energy", contents); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public JSONObject sugar(String crow, List<MenuDish> dishes) { |
||||
|
Map<String, Ingredient> 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<Long, BigDecimal> 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))); |
||||
|
|
||||
|
Map<Long, BigDecimal> 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)) |
||||
|
).reduce(BigDecimal::add).orElse(BigDecimal.ZERO))); |
||||
|
|
||||
|
Map<Long, BigDecimal> oil = 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)) |
||||
|
).reduce(BigDecimal::add).orElse(BigDecimal.ZERO))); |
||||
|
|
||||
|
JSONObject result = new JSONObject(); |
||||
|
result.put("crow", crow); |
||||
|
result.put("salt", salt); |
||||
|
result.put("sugar", sugar); |
||||
|
result.put("oil", oil); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public void export(Menu menu, ExcelWriter excelWriter) { |
||||
|
List<String> crows = menu.getCrows(); |
||||
|
crows.forEach(crow -> { |
||||
|
List<List<String>> headers = Lists.newArrayList(); |
||||
|
headers.add(Lists.newArrayList("日均营养分析", "营养素")); |
||||
|
headers.add(Lists.newArrayList("日均营养分析", "实际摄入")); |
||||
|
headers.add(Lists.newArrayList("日均营养分析", "标准范围")); |
||||
|
//headers.add(Lists.newArrayList("日均营养分析", "UL值"));
|
||||
|
headers.add(Lists.newArrayList("日均营养分析", "溢出范围")); |
||||
|
headers.add(Lists.newArrayList("日均营养分析", "评价")); |
||||
|
|
||||
|
JSONObject nutrition = nutrition(menu, 0, crow); |
||||
|
JSONArray ingredient = nutrition.getJSONArray("ingredient"); |
||||
|
if (ingredient == null) { |
||||
|
return; |
||||
|
} |
||||
|
//List<List<Object>> 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<List<Object>> 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()); |
||||
|
}); |
||||
|
|
||||
|
crows.forEach(crow -> { |
||||
|
List<List<String>> headers = Lists.newArrayList(); |
||||
|
headers.add(Lists.newArrayList("日均能量来源分布", "能量占比")); |
||||
|
headers.add(Lists.newArrayList("日均能量来源分布", "要求(%)")); |
||||
|
headers.add(Lists.newArrayList("日均能量来源分布", "实际摄入(%)")); |
||||
|
headers.add(Lists.newArrayList("日均能量来源分布", "评价")); |
||||
|
|
||||
|
JSONArray energy = energy(0, crow, menuDishService.query(menu.getId(), menu.getVender())).getJSONArray("energy"); |
||||
|
if (energy == null) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
List<List<Object>> 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()); |
||||
|
}); |
||||
|
|
||||
|
crows.forEach(crow -> { |
||||
|
List<List<String>> headers = Lists.newArrayList(); |
||||
|
headers.add(Lists.newArrayList("食材种类统计", "")); |
||||
|
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())); |
||||
|
if (types == null) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
List<List<Object>> 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"), x.get("standard"), x.get("supplied"), x.get("details"), x.get("lack"))).collect(Collectors.toList())); |
||||
|
} |
||||
|
Map<Long, List<JSONObject>> dayRule = types.getObject("dayRule", new TypeReference<Map<Long, List<JSONObject>>>() { |
||||
|
}); |
||||
|
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"), x.get("standard"), x.get("supplied"), x.get("details"), x.get("lack"))).collect(Collectors.toList()))); |
||||
|
} |
||||
|
excelWriter.write(contents, EasyExcel.writerSheet("食材种类统计-" + crow).head(headers).build()); |
||||
|
}); |
||||
|
|
||||
|
crows.forEach(crow -> { |
||||
|
List<List<String>> headers = Lists.newArrayList(); |
||||
|
headers.add(Lists.newArrayList("烹饪方式统计", "")); |
||||
|
headers.add(Lists.newArrayList("烹饪方式统计", "烹饪方式")); |
||||
|
headers.add(Lists.newArrayList("烹饪方式统计", "菜品数量")); |
||||
|
|
||||
|
JSONObject polys = poly(crow, menuDishService.query(menu.getId(), menu.getVender())); |
||||
|
if (polys == null) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
List<List<Object>> contents = polys.entrySet().stream().filter(kv -> StringUtils.isNumeric(kv.getKey())).map(kv -> ((Map<Object, Object>) 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()); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private JSONObject toEnergyContent(BigDecimal total, String key, BigDecimal value, Range<Integer> standard) { |
||||
|
BigDecimal percentage = total.intValue() == 0 ? BigDecimal.ZERO : value.divide(total, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)); |
||||
|
percentage = percentage.setScale(2, RoundingMode.HALF_UP); |
||||
|
|
||||
|
JSONObject result = JSONObject.of("name", enumService.getNutrient(key).getValue() + "/总能量"); |
||||
|
result.put("standard", String.format("%s~%s", standard.lowerEndpoint(), standard.upperEndpoint())); |
||||
|
result.put("value", percentage); |
||||
|
result.put("conclusion", standard.lowerEndpoint() > percentage.intValue() ? "略低" : standard.upperEndpoint() < percentage.intValue() ? "略高" : "合适"); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
private Nutrition getNutrition(Menu menu) { |
||||
|
Nutrition nutrition = nutritionService.get(menu.getNutrient()); |
||||
|
if (CollectionUtils.isNotEmpty(menu.getMeals())) { |
||||
|
if (MealType.values().length > menu.getMeals().size()) { |
||||
|
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; |
||||
|
} |
||||
|
}).reduce(BigDecimal::add).orElse(BigDecimal.ZERO); |
||||
|
|
||||
|
if (scale.intValue() < 100) { |
||||
|
Map<String, Map<String, Map<String, BigDecimal>>> ingredient = nutrition.getIngredient(); |
||||
|
ingredient.forEach((crow, value) -> value.forEach((nutrient, items) -> items.forEach((k, v) -> ingredient.get(crow).get(nutrient).put(k, v.multiply(scale).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP))))); |
||||
|
nutrition.setIngredient(ingredient); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return nutrition; |
||||
|
} |
||||
|
|
||||
|
private static BigDecimal calculatePercentage(BigDecimal value, BigDecimal base) { |
||||
|
BigDecimal percentage = value.subtract(base).divide(base, 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)); |
||||
|
return percentage.setScale(2, RoundingMode.HALF_UP); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,105 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.google.common.collect.Lists; |
||||
|
import com.mathvision.diet.domian.MenuStatus; |
||||
|
import com.mathvision.diet.entity.Menu; |
||||
|
import com.mathvision.diet.entity.MenuApprove; |
||||
|
import com.mathvision.diet.repository.MenuApproveRepository; |
||||
|
import com.mathvision.diet.repository.MenuRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.jpa.domain.Specification; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import javax.persistence.criteria.CriteriaBuilder; |
||||
|
import javax.persistence.criteria.Predicate; |
||||
|
import java.time.Instant; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class MenuReviewService { |
||||
|
// private static final List<MenuStatus> SUPPORTED_STATUS = Lists.newArrayList(MenuStatus.submit, MenuStatus.pass, MenuStatus.reject);
|
||||
|
// @Resource
|
||||
|
// private MenuRepository menuRepository;
|
||||
|
//
|
||||
|
// @Resource
|
||||
|
// private MenuApproveRepository menuApproveRepository;
|
||||
|
//
|
||||
|
// @PostConstruct
|
||||
|
// @Scheduled(cron = "0 0 0/6 * * *")
|
||||
|
// public void init() {
|
||||
|
// menuApproveRepository.scanExpired();
|
||||
|
// }
|
||||
|
//
|
||||
|
// public void submit(Long id, String operator) {
|
||||
|
// menuRepository.updateStatusAndOperateById(MenuStatus.submit, operator, id);
|
||||
|
// }
|
||||
|
//
|
||||
|
// public void pass(Long id, String reason, String operator) {
|
||||
|
// Instant datetime = Instant.now();
|
||||
|
// menuRepository.updateStatusAndApproveAndOperateById(MenuStatus.pass, reason, operator, id);
|
||||
|
// menuApproveRepository.save(MenuApprove.builder().menu(id).pass(true).approve(reason).operate(operator).created(datetime).modify(datetime).build());
|
||||
|
// }
|
||||
|
//
|
||||
|
// public void reject(Long id, String reason, String operator) {
|
||||
|
// Instant datetime = Instant.now();
|
||||
|
// menuRepository.updateStatusAndApproveAndOperateById(MenuStatus.reject, reason, operator, id);
|
||||
|
// menuApproveRepository.save(MenuApprove.builder().menu(id).pass(false).approve(reason).operate(operator).created(datetime).modify(datetime).build());
|
||||
|
// }
|
||||
|
//
|
||||
|
// public void disable(Long id, String operator) {
|
||||
|
// menuRepository.updateStatusAndOperateById(MenuStatus.disabled, operator, id);
|
||||
|
// }
|
||||
|
//
|
||||
|
// public Object count() {
|
||||
|
// return menuRepository.count(Lists.newArrayList(MenuStatus.submit, MenuStatus.pass, MenuStatus.reject));
|
||||
|
// }
|
||||
|
//
|
||||
|
// public Page<Menu> list(Long vender, MenuStatus status, String name, Date startTime, Date endTime, PageRequest pageRequest) {
|
||||
|
// return menuRepository.findAll(toSpecification(vender, status, name, startTime, endTime), pageRequest);
|
||||
|
// }
|
||||
|
//
|
||||
|
// private Specification<Menu> toSpecification(Long vender, MenuStatus status, String name, Date startTime, Date endTime) {
|
||||
|
// return (root, query, builder) -> {
|
||||
|
// List<Predicate> predicates = new ArrayList<>();
|
||||
|
//
|
||||
|
// if (vender != null && vender > 0) {
|
||||
|
// predicates.add(builder.equal(root.get("vender"), vender));
|
||||
|
// }
|
||||
|
//
|
||||
|
// if( status != null && SUPPORTED_STATUS.contains(status)) {
|
||||
|
// predicates.add(builder.equal(root.get("status"), status));
|
||||
|
// } else {
|
||||
|
// CriteriaBuilder.In<Object> in = builder.in(root.get("status"));
|
||||
|
// Lists.newArrayList(MenuStatus.submit, MenuStatus.pass, MenuStatus.reject).forEach(in::value);
|
||||
|
// predicates.add(in);
|
||||
|
// }
|
||||
|
//
|
||||
|
// if (startTime != null) {
|
||||
|
// predicates.add(builder.greaterThanOrEqualTo(root.get("modify"), startTime.toInstant()));
|
||||
|
// }
|
||||
|
//
|
||||
|
// if (endTime != null) {
|
||||
|
// predicates.add(builder.lessThanOrEqualTo(root.get("modify"), endTime.toInstant()));
|
||||
|
// }
|
||||
|
//
|
||||
|
// if (StringUtils.isNotBlank(name)) {
|
||||
|
// predicates.add(builder.like(root.get("name"), "%" + name + "%"));
|
||||
|
// }
|
||||
|
//
|
||||
|
// if (predicates.size() > 1) {
|
||||
|
// return builder.and(predicates.toArray(new Predicate[0]));
|
||||
|
// } else {
|
||||
|
// return predicates.get(0);
|
||||
|
// }
|
||||
|
// };
|
||||
|
// }
|
||||
|
} |
||||
@ -0,0 +1,138 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.mathvision.diet.domian.MenuDishItemDTO; |
||||
|
import com.mathvision.diet.domian.MenuStatus; |
||||
|
import com.mathvision.diet.entity.Menu; |
||||
|
import com.mathvision.diet.entity.MenuDish; |
||||
|
import com.mathvision.diet.repository.MenuDishRepository; |
||||
|
import com.mathvision.diet.repository.MenuRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.jpa.domain.Specification; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import javax.persistence.criteria.Predicate; |
||||
|
import java.time.Instant; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class MenuService { |
||||
|
|
||||
|
@Resource |
||||
|
DishService dishService; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuRepository menuRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuDishRepository menuDishRepository; |
||||
|
|
||||
|
public List<Menu> add(List<Menu> menuList) { |
||||
|
return menuRepository.saveAll(menuList); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public List<Long> copy(Menu menu, String name, List<Long> vendors, String operator) { |
||||
|
Instant dateTime = Instant.now(); |
||||
|
List<MenuDish> menuDishes= menuDishRepository.findByMenu(menu.getId()); |
||||
|
List<Menu> menus = vendors.stream().map(vender -> Menu.builder().name(name).meals(menu.getMeals()).crows(menu.getCrows()).scale(menu.getCrows().stream().collect(Collectors.toMap(x -> x, x -> 0))).day(menu.getDay()).nutrient(menu.getNutrient()).month(menu.getMonth()).vender(vender).status(MenuStatus.draft).operate(operator).created(dateTime).modify(dateTime).build()).collect(Collectors.toList()); |
||||
|
menus = add(menus); |
||||
|
List<MenuDish> dishes = menus.stream().map(v -> menuDishes.stream().map(dish -> MenuDish.builder().vender(v.getVender()).menu(v.getId()).dish(dish.getVender().equals(v.getVender()) ? dish.getDish() : dishService.copy(dish.getDish(), v.getVender(), operator, dateTime).getId()).day(dish.getDay()).meal(dish.getMeal()).name(dish.getName()).marks(dish.getMarks()).poly(dish.getPoly()).label(dish.getLabel()).ingredient(dish.getIngredient()).operate(operator).created(dateTime).modify(dateTime).build()).collect(Collectors.toList())).flatMap(List::stream).collect(Collectors.toList()); |
||||
|
menuDishRepository.saveAll(dishes); |
||||
|
return menus.stream().map(Menu::getId).collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void delete(Long id, Long vender, String operator) { |
||||
|
if (vender == null || vender <= 0) { |
||||
|
menuRepository.deleteById(id); |
||||
|
menuDishRepository.deleteByMenu(id); |
||||
|
} else { |
||||
|
menuRepository.deleteByIdAndVender(id, vender); |
||||
|
menuDishRepository.deleteByMenuAndVender(id, vender); |
||||
|
} |
||||
|
log.info("[MenuService] delete id = " + id + ", vender = " + vender + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void delete(Long vender, String operator) { |
||||
|
menuRepository.deleteByVender(vender); |
||||
|
menuDishRepository.deleteByVender(vender); |
||||
|
log.info("[MenuService] delete vender = " + vender + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public void update(Menu menu) { |
||||
|
menuDishRepository.deleteByMenuAndDayNotInAndMealNotIn(menu.getId(), menu.getDay(), menu.getMeals()); |
||||
|
menuDishRepository.findByMenu(menu.getId()).forEach(x -> { |
||||
|
List<MenuDishItemDTO> ingredient = x.getIngredient(); |
||||
|
if (CollectionUtils.isNotEmpty(ingredient)) { |
||||
|
ingredient.forEach(i -> i.setValue(i.getValue().entrySet().stream().filter(crow -> menu.getCrows().contains(crow.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)))); |
||||
|
x.setOperate(menu.getOperate()); |
||||
|
x.setModify(menu.getModify()); |
||||
|
menuDishRepository.save(x); |
||||
|
} |
||||
|
}); |
||||
|
menuRepository.save(menu); |
||||
|
log.info("[MenuService] update id = " + menu.getId() + ", vender = " + menu.getVender() + ", operator = " + menu.getOperate()); |
||||
|
} |
||||
|
|
||||
|
public Menu get(Long id) { |
||||
|
return menuRepository.findById(id).orElse(null); |
||||
|
} |
||||
|
|
||||
|
public Menu get(Long id, Long vender) { |
||||
|
return menuRepository.findByIdAndVender(id, vender); |
||||
|
} |
||||
|
|
||||
|
public List<Menu> getByNutrition(Long nutrition) { |
||||
|
return menuRepository.findByNutrient(nutrition); |
||||
|
} |
||||
|
|
||||
|
public Page<Menu> list(Long vender, String name, MenuStatus status, Date startTime, Date endTime, PageRequest pageRequest) { |
||||
|
return menuRepository.findAll(toSpecification(vender, name, status, startTime, endTime), pageRequest); |
||||
|
} |
||||
|
|
||||
|
private Specification<Menu> toSpecification(Long vender, String name, MenuStatus status, Date startTime, Date endTime) { |
||||
|
return (root, query, builder) -> { |
||||
|
List<Predicate> predicates = new ArrayList<>(); |
||||
|
|
||||
|
if (vender != null && vender > 0) { |
||||
|
predicates.add(builder.equal(root.get("vender"), vender)); |
||||
|
} |
||||
|
|
||||
|
if (status == null || MenuStatus.publish.equals(status)) { |
||||
|
predicates.add(builder.notEqual(root.get("status"), MenuStatus.publish.getCode())); |
||||
|
} else { |
||||
|
predicates.add(builder.equal(root.get("status"), status)); |
||||
|
} |
||||
|
|
||||
|
if (startTime != null) { |
||||
|
predicates.add(builder.greaterThanOrEqualTo(root.get("modify"), startTime.toInstant())); |
||||
|
} |
||||
|
|
||||
|
if (endTime != null) { |
||||
|
predicates.add(builder.lessThanOrEqualTo(root.get("modify"), endTime.toInstant())); |
||||
|
} |
||||
|
|
||||
|
if (StringUtils.isNotBlank(name)) { |
||||
|
predicates.add(builder.like(root.get("name"), "%" + name + "%")); |
||||
|
} |
||||
|
|
||||
|
if (predicates.size() > 1) { |
||||
|
return builder.and(predicates.toArray(new Predicate[0])); |
||||
|
} else { |
||||
|
return predicates.get(0); |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,104 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.google.common.collect.Lists; |
||||
|
import com.mathvision.diet.entity.Nutrition; |
||||
|
import com.mathvision.diet.repository.NutritionRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.collections4.MapUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.util.Assert; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class NutritionService { |
||||
|
|
||||
|
@Resource |
||||
|
private EnumService enumService; |
||||
|
|
||||
|
@Resource |
||||
|
private VenderService venderService; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuService menuService; |
||||
|
|
||||
|
@Resource |
||||
|
private NutritionRepository nutritionRepository; |
||||
|
|
||||
|
@PostConstruct |
||||
|
private void init() { |
||||
|
nutritionRepository.findAll().stream().filter(x -> CollectionUtils.isEmpty(x.getCrows()) && MapUtils.isNotEmpty(x.getIngredient())).forEach(x -> { |
||||
|
x.setCrows(Lists.newArrayList(x.getIngredient().keySet())); |
||||
|
nutritionRepository.save(x); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public Nutrition add(Nutrition nutrition, String operator) { |
||||
|
check(nutrition, operator); |
||||
|
log.info("[NutritionService] add name = " + nutrition.getName() + ", operator = " + operator); |
||||
|
return nutritionRepository.save(nutrition); |
||||
|
} |
||||
|
|
||||
|
public void delete(long id, String operator) { |
||||
|
Assert.isTrue(CollectionUtils.isEmpty(menuService.getByNutrition(id)), "[参数错误]该营养计划使用中不可删除!"); |
||||
|
nutritionRepository.deleteById(id); |
||||
|
log.info("[NutritionService] delete id = " + id + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public Nutrition update(Nutrition nutrition, String operator) { |
||||
|
check(nutrition, operator); |
||||
|
log.info("[NutritionService] update name = " + nutrition.getName() + ", operator = " + operator); |
||||
|
return nutritionRepository.save(nutrition); |
||||
|
} |
||||
|
|
||||
|
public boolean exists(Long id) { |
||||
|
return nutritionRepository.existsById(id); |
||||
|
} |
||||
|
|
||||
|
public boolean notExists(String name) { |
||||
|
return !nutritionRepository.existsByName(name); |
||||
|
} |
||||
|
|
||||
|
public Nutrition get(Long id) { |
||||
|
return nutritionRepository.findById(id).orElse(null); |
||||
|
} |
||||
|
|
||||
|
public Nutrition get(String name) { |
||||
|
return nutritionRepository.findByName(name); |
||||
|
} |
||||
|
|
||||
|
public List<Nutrition> query(Long vender, String name) { |
||||
|
List<Nutrition> result = nutritionRepository.findByNameLike('%' + name + '%'); |
||||
|
if (vender != null && vender !=0) { |
||||
|
return result.stream().filter(x -> x.getVendors().contains(vender)).collect(Collectors.toList()); |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public Page<Nutrition> list(String name, PageRequest pageRequest) { |
||||
|
return StringUtils.isBlank(name) ? nutritionRepository.findAll(pageRequest) : nutritionRepository.findByNameLikeOrderByIdDesc('%' + name + '%', pageRequest); |
||||
|
} |
||||
|
|
||||
|
private void check(Nutrition nutrition, String operator) { |
||||
|
nutrition.setVendors(nutrition.getVendors().stream().filter(x -> venderService.exists(x)).collect(Collectors.toList())); |
||||
|
Assert.isTrue(StringUtils.isNotBlank(nutrition.getName()) && |
||||
|
CollectionUtils.isNotEmpty(nutrition.getVendors()) && |
||||
|
nutrition.getOverflow() != null && |
||||
|
(nutrition.getIngredient() == null || nutrition.getIngredient().entrySet().stream().allMatch(x -> x.getValue().keySet().stream().allMatch(n -> enumService.checkNutrient(n)))) |
||||
|
, "[参数错误]必填参数未填写,或者单位类别为空、类型和营养素不在取值范围内!"); |
||||
|
|
||||
|
Instant dateTime = Instant.now(); |
||||
|
nutrition.setOperate(operator); |
||||
|
nutrition.setCreated(dateTime); |
||||
|
nutrition.setModify(dateTime); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.mathvision.diet.entity.Sugar; |
||||
|
import com.mathvision.diet.repository.SugarRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.jpa.domain.Specification; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import javax.persistence.criteria.Predicate; |
||||
|
import java.time.LocalDate; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class SugarService { |
||||
|
|
||||
|
@Resource |
||||
|
private SugarRepository sugarRepository; |
||||
|
|
||||
|
public void save(Sugar sugar) { |
||||
|
sugarRepository.save(sugar); |
||||
|
} |
||||
|
|
||||
|
public void delete(Sugar sugar) { |
||||
|
sugarRepository.delete(sugar); |
||||
|
} |
||||
|
|
||||
|
public void delete(Long vender) { |
||||
|
sugarRepository.deleteByVender(vender); |
||||
|
} |
||||
|
|
||||
|
public Sugar get(Long id, Long vender) { |
||||
|
return sugarRepository.findByIdAndVender(id, vender); |
||||
|
} |
||||
|
|
||||
|
public boolean exist(String name, Long vender) { |
||||
|
return sugarRepository.existsByVenderAndName(vender, name); |
||||
|
} |
||||
|
|
||||
|
public Page<Sugar> list(Long vender, LocalDate startTime, LocalDate endTime, PageRequest pageRequest) { |
||||
|
return sugarRepository.findAll(toSpecification(vender, startTime, endTime), pageRequest); |
||||
|
} |
||||
|
|
||||
|
private Specification<Sugar> toSpecification(Long vender, LocalDate startTime, LocalDate endTime) { |
||||
|
return (root, query, builder) -> { |
||||
|
List<Predicate> predicates = new ArrayList<>(); |
||||
|
|
||||
|
predicates.add(builder.equal(root.get("vender"), vender)); |
||||
|
|
||||
|
if (startTime != null) { |
||||
|
predicates.add(builder.greaterThanOrEqualTo(root.get("startTime"), startTime)); |
||||
|
} |
||||
|
|
||||
|
if (endTime != null) { |
||||
|
predicates.add(builder.lessThanOrEqualTo(root.get("endTime"), endTime)); |
||||
|
} |
||||
|
|
||||
|
if (predicates.size() > 1) { |
||||
|
return builder.and(predicates.toArray(new Predicate[0])); |
||||
|
} else { |
||||
|
return predicates.get(0); |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,274 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.google.common.collect.Lists; |
||||
|
import com.mathvision.diet.domain.UserDO; |
||||
|
import com.mathvision.diet.domian.AuthType; |
||||
|
import com.mathvision.diet.domian.ClientType; |
||||
|
import com.mathvision.diet.domian.RoleType; |
||||
|
import com.mathvision.diet.entity.*; |
||||
|
import com.mathvision.diet.repository.*; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
import org.springframework.util.Assert; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Objects; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class UserService { |
||||
|
|
||||
|
@Resource |
||||
|
private EnumService enumService; |
||||
|
|
||||
|
@Resource |
||||
|
private UserRepository userRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private UserLogRepository userLogRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private UserSessionRepository userSessionRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private UserMessageRepository userMessageRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private UserRoleRepository userRoleRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private RoleRepository roleRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private VenderRepository venderRepository; |
||||
|
|
||||
|
@PostConstruct |
||||
|
@Scheduled(cron = "0 0 0/6 * * *") |
||||
|
public void init() { |
||||
|
userLogRepository.scanExpired(); |
||||
|
userMessageRepository.scanExpired(); |
||||
|
userSessionRepository.scanExpired(); |
||||
|
} |
||||
|
|
||||
|
public UserDO login(String uid, String password, ClientType clientType, String clientVersion) { |
||||
|
Assert.isTrue(checkUser(uid, password), "[参数错误]用户名密码错误!"); |
||||
|
userLogRepository.save(UserLog.builder().uid(uid).clientType(clientType).clientVersion(clientVersion).login(Instant.now()).build()); |
||||
|
log.info("[UserService] login uid = " + uid + ", clientType = " + clientType + ", clientVersion = " + clientVersion); |
||||
|
return queryUser(uid); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void addUser(String uid, String name, String password, Long roleId, Long venderId, String operator) { |
||||
|
Assert.isTrue(checkUser(uid), "[参数错误]用户名重复!"); |
||||
|
Assert.isTrue(StringUtils.isNotBlank(name), "[参数错误]姓名必填!"); |
||||
|
Assert.isTrue(StringUtils.isNotBlank(password) && password.length() == 16, "[参数错误]密码为空, 或者密码长度错误!"); |
||||
|
Assert.isTrue(checkRole(roleId, venderId), "[参数错误]未赋初始角色,或者该角色错误!"); |
||||
|
Instant dateTime = Instant.now(); |
||||
|
User user = User.builder().uid(uid).name(name).pwd(password).status(true).created(dateTime).modify(dateTime).build(); |
||||
|
UserRole userRole = UserRole.builder().roleId(roleId).uid(uid).vender(venderId).operate(operator).created(dateTime).modify(dateTime).build(); |
||||
|
|
||||
|
userRepository.save(user); |
||||
|
userRoleRepository.save(userRole); |
||||
|
log.info("[UserService] addUser venderId= " + venderId + ", uid = " + uid + ", roleId = " + roleId + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void delUser(Long venderId, String operator) { |
||||
|
List<String> users = listUser(venderId).stream().map(UserDO::getUid).collect(Collectors.toList()); |
||||
|
if (!users.isEmpty()) { |
||||
|
userRepository.deleteByUidIn(users); |
||||
|
} |
||||
|
userRoleRepository.deleteByVender(venderId); |
||||
|
roleRepository.deleteByVender(venderId); |
||||
|
log.info("[UserService] delUser venderId = " + venderId + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void delUser(String uid, Long venderId, String operator) { |
||||
|
Assert.isTrue(checkRole(uid, venderId), "[参数错误]该用户不是您单位用户!"); |
||||
|
Assert.isTrue(countRole(venderId, uid) > 0, "[参数错误]至少保留一个管理员!"); |
||||
|
if (userRoleRepository.deleteByUidAndVender(uid, venderId) > 0) { |
||||
|
userRepository.deleteByUid(uid); |
||||
|
} |
||||
|
log.info("[UserService] delUser uid = " + uid + "venderId = " + venderId + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public void changeUser(String uid, String name, String password, Long roleId, Long venderId, String operator) { |
||||
|
Assert.isTrue(checkRole(uid, venderId), "[参数错误]该用户不是您单位用户!"); |
||||
|
if (roleId != null) { |
||||
|
if (roleId > 0) { |
||||
|
Assert.isTrue(checkRole(roleId, venderId), "[参数错误]该角色不属于您单位!"); |
||||
|
} else { |
||||
|
Assert.isTrue(countRole(venderId, uid) > 0, "[参数错误]至少保留一个管理员!"); |
||||
|
} |
||||
|
userRoleRepository.updateRoleIdAndOperateByUidAndVender(roleId, operator, uid, venderId); |
||||
|
log.info("[UserService] changeUser uid = " + uid + ", roleId = " + roleId + ", operator = " + operator); |
||||
|
} |
||||
|
if (StringUtils.isNotBlank(name)) { |
||||
|
userRepository.updateNameByUid(name, uid); |
||||
|
log.info("[UserService] changeUser uid = " + uid + ", name = " + name + ", operator = " + operator); |
||||
|
} |
||||
|
if (StringUtils.isNotBlank(password)) { |
||||
|
userRepository.updatePwdByUid(password, uid); |
||||
|
log.info("[UserService] changeUser uid = " + uid + ", password = " + password + ", operator = " + operator); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public UserDO queryUser(String uid) { |
||||
|
UserDO result = new UserDO(); |
||||
|
User user = userRepository.findByUidAndStatus(uid, true); |
||||
|
if (user == null) { |
||||
|
log.info("[UserService] queryUser user=null uid = " + uid); |
||||
|
return null; |
||||
|
} |
||||
|
result.setUid(user.getUid()); |
||||
|
result.setName(user.getName()); |
||||
|
result.setPhone(user.getPhone()); |
||||
|
result.setTime(user.getCreated()); |
||||
|
|
||||
|
UserRole userRole = userRoleRepository.findByUid(uid); |
||||
|
if (userRole == null) { |
||||
|
log.info("[UserService] queryUser userRole=null uid = " + uid); |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
if (userRole.getVender() != 0) { |
||||
|
Vender vender = venderRepository.findByIdAndStatus(userRole.getVender(), true); |
||||
|
if (userRole.getVender() != 0 && vender == null) { |
||||
|
log.info("[UserService] queryUser vender=null or closed vender uid=" + uid + ", venderId=" + userRole.getVender()); |
||||
|
return null; |
||||
|
} |
||||
|
result.setVender(vender); |
||||
|
} |
||||
|
|
||||
|
Role role = query(userRole.getRoleId()); |
||||
|
if (role != null) { |
||||
|
result.setRoleId(role.getId()); |
||||
|
result.setRoleName(role.getRoleName()); |
||||
|
result.setRoleType(role.getRoleType().getType()); |
||||
|
result.setRoleItems(enumService.getRoleItems(role.getRoleItems())); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public List<UserDO> listUser(Long venderId) { |
||||
|
if (venderId == null || venderId < 0) { |
||||
|
return Lists.newArrayList(); |
||||
|
} |
||||
|
Map<Long, Role> roles = roleRepository.findByVender(venderId).stream().collect(Collectors.toMap(Role::getId, v -> v)); |
||||
|
Map<String,Role> userRole = userRoleRepository.findByVender(venderId).stream().collect(Collectors.toMap(UserRole::getUid, v -> roles.getOrDefault(v.getRoleId(), new Role()))); |
||||
|
return userRepository.findByUidIn(userRole.keySet()).stream().map(user -> { |
||||
|
Role role = userRole.getOrDefault(user.getUid(), null); |
||||
|
return UserDO.builder() |
||||
|
.uid(user.getUid()) |
||||
|
.name(user.getName()) |
||||
|
.phone(user.getPhone()) |
||||
|
.time(user.getCreated()) |
||||
|
.roleId(role != null ? role.getId() : null) |
||||
|
.roleName(role != null ? role.getRoleName() : null) |
||||
|
.build(); |
||||
|
}).collect(Collectors.toList()); |
||||
|
} |
||||
|
|
||||
|
public List<RoleItem> listRoleItems(AuthType itemType) { |
||||
|
return enumService.getRoleItems(itemType); |
||||
|
} |
||||
|
|
||||
|
public Role addRole(Long venderId) { |
||||
|
List<Long> items = listRoleItems(AuthType.CLIENT).stream().map(RoleItem::getId).collect(Collectors.toList()); |
||||
|
return addRole("超级管理员", items, RoleType.SYSTEM, AuthType.CLIENT, venderId, "system"); |
||||
|
} |
||||
|
|
||||
|
public Role addRole(String roleName, List<Long> items, RoleType roleType, AuthType itemType, Long venderId, String operator) { |
||||
|
List<Long> allItem = listRoleItems(itemType).stream().map(RoleItem::getId).collect(Collectors.toList()); |
||||
|
items = items == null ? Lists.newArrayList() : items.stream().filter(Objects::nonNull).filter(allItem::contains).collect(Collectors.toList()); |
||||
|
Assert.isTrue(StringUtils.isNotBlank(roleName) && venderId != null, "[参数错误]角色名称不能为空!"); |
||||
|
Instant dateTime = Instant.now(); |
||||
|
Role role = Role.builder().vender(venderId).roleType(roleType).roleName(roleName).roleItems(items).operate(operator).created(dateTime).modify(dateTime).build(); |
||||
|
log.info("[UserService] addRole venderId=" + venderId + ", operator=" + operator); |
||||
|
return roleRepository.save(role); |
||||
|
} |
||||
|
|
||||
|
public void delRole(Long roleId, Long venderId, String operator) { |
||||
|
Assert.isTrue(roleId != null && roleId > 0 && roleRepository.existsByIdAndVender(roleId, venderId) && !userRoleRepository.existsByRoleIdAndVender(roleId, venderId), "[参数错误]角色使用中,不能删除!"); |
||||
|
roleRepository.deleteByIdAndVenderAndRoleTypeNot(roleId, venderId, RoleType.SYSTEM); |
||||
|
log.info("[UserService] delRole venderId=" + venderId + ",roleId=" + roleId + ", operator=" + operator); |
||||
|
} |
||||
|
|
||||
|
public void changeRole(Long roleId, String roleName, List<Long> items, AuthType itemType, Long venderId, String operator) { |
||||
|
Assert.isTrue(roleId != null && roleId > 0 && roleRepository.existsByIdAndVender(roleId, venderId), "[参数错误]该角色不属于您!"); |
||||
|
if(StringUtils.isNotBlank(roleName)) { |
||||
|
roleRepository.updateRoleNameAndOperateByIdAndVenderAndRoleTypeNot(roleName, operator, roleId, venderId); |
||||
|
log.info("[UserService] changeRole venderId=" + venderId + ", roleName=" + roleName + ", roleId=" + roleId + ", operator=" + operator); |
||||
|
} |
||||
|
|
||||
|
List<Long> allItem = listRoleItems(itemType).stream().map(RoleItem::getId).collect(Collectors.toList()); |
||||
|
items = items == null ? Lists.newArrayList() : items.stream().filter(Objects::nonNull).filter(allItem::contains).collect(Collectors.toList()); |
||||
|
if(!items.isEmpty()) { |
||||
|
roleRepository.updateRoleItemsAndOperateByIdAndVenderAndRoleTypeNot(JSON.toJSONString(items), operator, roleId, venderId); |
||||
|
log.info("[UserService] changeRole venderId=" + venderId + ", allItem=" + JSON.toJSONString(items) + ", roleId=" + roleId + ", operator=" + operator); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public List<Role> listRole(Long venderId) { |
||||
|
return roleRepository.findByVender(venderId); |
||||
|
} |
||||
|
|
||||
|
public Role query(Long roleId) { |
||||
|
return roleId != null && roleId > 0 ? roleRepository.findById(roleId).orElse(null) : null; |
||||
|
} |
||||
|
|
||||
|
public boolean checkUser(String uid, String password) { |
||||
|
return StringUtils.isNotBlank(uid) && StringUtils.isNotBlank(password) && userRepository.existsByUidAndPwdAndStatus(uid, password, true); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查看用户是否存在 |
||||
|
*/ |
||||
|
public boolean checkUser(String uid) { |
||||
|
return StringUtils.isBlank(uid) || !userRepository.existsByUid(uid); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 查看用户属于该单位 |
||||
|
*/ |
||||
|
public boolean checkRole(String uid, Long venderId) { |
||||
|
return StringUtils.isNotBlank(uid) && venderId != null && userRoleRepository.existsByUidAndVender(uid, venderId); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 检查权限属于该单位 |
||||
|
*/ |
||||
|
public boolean checkRole(Long roleId, Long venderId) { |
||||
|
return roleId != null && roleId > 0 && venderId != null && roleRepository.existsByIdAndVender(roleId, venderId); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 统计管理员数量 |
||||
|
*/ |
||||
|
public long countRole(Long venderId, String uid) { |
||||
|
if (venderId == null || venderId < 0) { |
||||
|
return 0; |
||||
|
} |
||||
|
Role role = roleRepository.findByVenderForDefaultRole(venderId, RoleType.SYSTEM); |
||||
|
return role == null ? 0 : userRoleRepository.countByRoleIdAndVenderAndUidNot(role.getId(), venderId, uid); |
||||
|
} |
||||
|
|
||||
|
public void logout(String uid) { |
||||
|
if (StringUtils.isBlank(uid)) { |
||||
|
return; |
||||
|
} |
||||
|
userLogRepository.updateLogoutByUid(Instant.now(), uid); |
||||
|
log.info("[UserService] logout uid=" + uid); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,143 @@ |
|||||
|
package com.mathvision.diet.service; |
||||
|
|
||||
|
import com.mathvision.diet.domian.VenderType; |
||||
|
import com.mathvision.diet.entity.Vender; |
||||
|
import com.mathvision.diet.entity.VenderConfig; |
||||
|
import com.mathvision.diet.repository.VenderConfigRepository; |
||||
|
import com.mathvision.diet.repository.VenderRepository; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.scheduling.annotation.Scheduled; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import javax.annotation.PostConstruct; |
||||
|
import javax.annotation.Resource; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Service |
||||
|
public class VenderService { |
||||
|
@Resource |
||||
|
private VenderRepository venderRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private VenderConfigRepository venderConfigRepository; |
||||
|
|
||||
|
@Resource |
||||
|
private UserService userService; |
||||
|
|
||||
|
@Resource |
||||
|
private MenuService menuService; |
||||
|
|
||||
|
@Resource |
||||
|
private DishService dishService; |
||||
|
|
||||
|
@Resource |
||||
|
private IngredientService ingredientService; |
||||
|
|
||||
|
@Resource |
||||
|
private SugarService sugarService; |
||||
|
|
||||
|
@PostConstruct |
||||
|
@Scheduled(cron = "0 0 0/1 * * *") |
||||
|
public void init() { |
||||
|
venderRepository.scanExpired(); |
||||
|
} |
||||
|
|
||||
|
public VenderConfig queryConfig(Long venderId) { |
||||
|
if (venderId == null || venderId <= 0) { |
||||
|
log.info("[VenderService] queryConfig venderId = " + venderId); |
||||
|
return null; |
||||
|
} |
||||
|
return venderConfigRepository.findByVender(venderId); |
||||
|
} |
||||
|
|
||||
|
public void modConfig(Long venderId, BigDecimal breakfast, BigDecimal lunch, BigDecimal dinner, String operate) { |
||||
|
if (venderId == null || venderId <= 0) { |
||||
|
log.info("[VenderService] modConfig venderId = " + venderId + ", operate = " + operate); |
||||
|
return; |
||||
|
} |
||||
|
venderConfigRepository.updateBreakfastAndLunchAndDinnerAndOperateByVender(breakfast, lunch, dinner, operate, venderId); |
||||
|
log.info("[VenderService] modConfig success: venderId = " + venderId + ", operate = " + operate); |
||||
|
} |
||||
|
|
||||
|
public Vender queryVender(Long venderId) { |
||||
|
if (venderId == null || venderId <= 0) { |
||||
|
log.info("[VenderService] queryVender venderId = " + venderId); |
||||
|
return null; |
||||
|
} |
||||
|
return venderRepository.findById(venderId).orElse(null); |
||||
|
} |
||||
|
|
||||
|
public boolean exists(Long venderId) { |
||||
|
if (venderId == null || venderId <= 0) { |
||||
|
return false; |
||||
|
} |
||||
|
return venderRepository.existsById(venderId); |
||||
|
} |
||||
|
|
||||
|
public List<Vender> listVender(String keyword, List<Long> vendors) { |
||||
|
if (CollectionUtils.isNotEmpty(vendors)) { |
||||
|
return venderRepository.findByIdIn(vendors); |
||||
|
} |
||||
|
return StringUtils.isNotBlank(keyword) ? venderRepository.findByStatusAndNameLikeOrderByNameDesc(true, '%' + keyword + '%') : venderRepository.findByStatusOrderByNameAsc(true); |
||||
|
} |
||||
|
|
||||
|
public Page<Vender> pageVender(String keyword, VenderType type, PageRequest pageRequest) { |
||||
|
if (type == null) { |
||||
|
return StringUtils.isBlank(keyword) ? venderRepository.findAll(pageRequest) : venderRepository.findByNameLikeOrderByIdDesc('%' + keyword + '%', pageRequest); |
||||
|
} else { |
||||
|
return StringUtils.isBlank(keyword) ? venderRepository.findByCategoryOrderByIdDesc(type, pageRequest) : venderRepository.findByCategoryAndNameLikeOrderByIdDesc(type, '%' + keyword + '%', pageRequest); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void addVender(Vender vender, String password, String operator) { |
||||
|
Instant dateTime = Instant.now(); |
||||
|
vender.setStatus(true); |
||||
|
vender.setOperate(operator); |
||||
|
vender.setCreated(dateTime); |
||||
|
vender.setModify(dateTime); |
||||
|
Vender _vender = venderRepository.save(vender); |
||||
|
venderConfigRepository.save(VenderConfig.builder().vender(vender.getId()).breakfast(new BigDecimal(30)).lunch(new BigDecimal(35)).dinner(new BigDecimal(35)).operate(operator).created(dateTime).modify(dateTime).build()); |
||||
|
userService.addUser(_vender.getAccount(), _vender.getName(), password, userService.addRole(_vender.getId()).getId(), _vender.getId(), operator); |
||||
|
log.info("[VenderService] addVender venderId = " + vender.getName() + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void modVender(Vender vender, String operator) { |
||||
|
if (vender == null) return; |
||||
|
venderRepository.save(vender); |
||||
|
log.info("[VenderService] delVender venderId = " + vender.getId() + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
@Transactional |
||||
|
public void delVender(Long venderId, String operator) { |
||||
|
if (venderId == null || venderId <= 0) { |
||||
|
log.info("[VenderService] delVender venderId = " + venderId + ", operator = " + operator); |
||||
|
return; |
||||
|
} |
||||
|
venderRepository.deleteById(venderId); |
||||
|
venderConfigRepository.deleteByVender(venderId); |
||||
|
userService.delUser(venderId, operator); |
||||
|
ingredientService.delMark(venderId, operator); |
||||
|
dishService.delete(venderId, operator); |
||||
|
menuService.delete(venderId, operator); |
||||
|
sugarService.delete(venderId); |
||||
|
log.info("[VenderService] delVender venderId = " + venderId + ", operator = " + operator); |
||||
|
} |
||||
|
|
||||
|
public boolean checkName(String venderName) { |
||||
|
return !venderRepository.existsByName(venderName); |
||||
|
} |
||||
|
|
||||
|
public boolean checkAccount(String account) { |
||||
|
return userService.checkUser(account); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.word; |
||||
|
|
||||
|
import com.deepoove.poi.data.RowRenderData; |
||||
|
import lombok.Data; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
@Data |
||||
|
public class ServerTableData { |
||||
|
|
||||
|
/** |
||||
|
* 携带表格中真实数据 |
||||
|
*/ |
||||
|
private List<RowRenderData> serverDataList; |
||||
|
|
||||
|
/** |
||||
|
* 携带扩展列信息 |
||||
|
*/ |
||||
|
private List<String> extendedColumn; |
||||
|
|
||||
|
/** |
||||
|
* 需要合并的列,从0开始 |
||||
|
*/ |
||||
|
private Integer mergeColumn; |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
package com.mathvision.diet.word; |
||||
|
|
||||
|
import com.deepoove.poi.data.RowRenderData; |
||||
|
import com.deepoove.poi.policy.DynamicTableRenderPolicy; |
||||
|
import com.deepoove.poi.policy.TableRenderPolicy; |
||||
|
import com.deepoove.poi.util.TableTools; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.poi.xwpf.usermodel.TableWidthType; |
||||
|
import org.apache.poi.xwpf.usermodel.XWPFTable; |
||||
|
import org.apache.poi.xwpf.usermodel.XWPFTableRow; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class ServerTablePolicy extends DynamicTableRenderPolicy { |
||||
|
@Override |
||||
|
public void render(XWPFTable xwpfTable, Object tableData) throws Exception { |
||||
|
if (null == tableData) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 参数数据声明
|
||||
|
ServerTableData serverTableData = (ServerTableData) tableData; |
||||
|
List<RowRenderData> serverDataList = serverTableData.getServerDataList(); |
||||
|
List<String> extendedColumn = serverTableData.getExtendedColumn(); |
||||
|
Integer mergeColumn = serverTableData.getMergeColumn(); |
||||
|
int columnSize = xwpfTable.getRow(0).getTableCells().size(); |
||||
|
|
||||
|
// 新增扩展列
|
||||
|
if (CollectionUtils.isNotEmpty(extendedColumn)) { |
||||
|
for (int i = 0; i < extendedColumn.size(); i++) { |
||||
|
xwpfTable.addNewCol(); |
||||
|
columnSize++; |
||||
|
xwpfTable.getRow(0).getTableCells().get(columnSize - 1).setText(extendedColumn.get(i)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (CollectionUtils.isNotEmpty(serverDataList)) { |
||||
|
// 先删除一行, demo中第一行是为了调整 三线表 样式
|
||||
|
xwpfTable.removeRow(1); |
||||
|
|
||||
|
// 行从中间插入, 因此采用倒序渲染数据
|
||||
|
for (int i = serverDataList.size() - 1; i >= 0; i--) { |
||||
|
XWPFTableRow newRow = xwpfTable.insertNewTableRow(1); |
||||
|
newRow.setHeight(400); |
||||
|
for (int j = 0; j < columnSize; j++) { |
||||
|
newRow.createCell(); |
||||
|
} |
||||
|
// 渲染一行数据
|
||||
|
TableRenderPolicy.Helper.renderRow(newRow, serverDataList.get(i)); |
||||
|
} |
||||
|
// 定义需要合并的列索引(例如第一列)
|
||||
|
int startMergeIndex = 1; |
||||
|
String currentType = null; |
||||
|
|
||||
|
for (int i = 0; i < serverDataList.size(); i++) { |
||||
|
String typeNameData = serverDataList.get(i).getCells().get(mergeColumn).getParagraphs().get(0).getContents().get(0).toString(); |
||||
|
|
||||
|
if (i == 0) { |
||||
|
currentType = typeNameData; |
||||
|
} else { |
||||
|
if (!typeNameData.equals(currentType)) { |
||||
|
if (i - startMergeIndex > 0) { |
||||
|
TableTools.mergeCellsVertically(xwpfTable, mergeColumn, startMergeIndex, i + 1); |
||||
|
} |
||||
|
currentType = typeNameData; |
||||
|
startMergeIndex = i + 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 处理循环结束后的剩余数据
|
||||
|
if (serverDataList.size() - startMergeIndex > 1) { |
||||
|
TableTools.mergeCellsVertically(xwpfTable, mergeColumn, startMergeIndex, serverDataList.size()); |
||||
|
} |
||||
|
|
||||
|
// 自动调整宽度
|
||||
|
xwpfTable.setWidthType(TableWidthType.AUTO); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
|
||||
|
<parent> |
||||
|
<groupId>com.mathvision.diet</groupId> |
||||
|
<artifactId>diet</artifactId> |
||||
|
<version>1.0-SNAPSHOT</version> |
||||
|
</parent> |
||||
|
<artifactId>diet-dao</artifactId> |
||||
|
<packaging>jar</packaging> |
||||
|
|
||||
|
<properties> |
||||
|
<maven.compiler.source>8</maven.compiler.source> |
||||
|
<maven.compiler.target>8</maven.compiler.target> |
||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
</properties> |
||||
|
|
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.mysql</groupId> |
||||
|
<artifactId>mysql-connector-j</artifactId> |
||||
|
<scope>runtime</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.vladmihalcea</groupId> |
||||
|
<artifactId>hibernate-types-52</artifactId> |
||||
|
<version>2.21.1</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.googlecode.log4jdbc</groupId> |
||||
|
<artifactId>log4jdbc</artifactId> |
||||
|
<version>1.2</version> |
||||
|
<scope>runtime</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.commons</groupId> |
||||
|
<artifactId>commons-compress</artifactId> |
||||
|
<version>1.21</version> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
</project> |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.mathvision.diet.domian.AuthType; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class AuthTypeConvert implements AttributeConverter<AuthType,String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(AuthType type) { |
||||
|
return type == null ? null : type.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AuthType convertToEntityAttribute(String s) { |
||||
|
return AuthType.toType(s); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.alibaba.fastjson2.TypeReference; |
||||
|
import com.mathvision.diet.domian.DishItemDTO; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Converter |
||||
|
public class DishItemConvert implements AttributeConverter<List<DishItemDTO>, String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(List<DishItemDTO> stringList) { |
||||
|
return JSON.toJSONString(stringList); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<DishItemDTO> convertToEntityAttribute(String s) { |
||||
|
return JSON.parseObject(s, new TypeReference<List<DishItemDTO>>(){}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.mathvision.diet.domian.GenderType; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class GenderTypeConvert implements AttributeConverter<GenderType,String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(GenderType type) { |
||||
|
return type == null ? null : type.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public GenderType convertToEntityAttribute(String s) { |
||||
|
return GenderType.toType(s); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.alibaba.fastjson2.TypeReference; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class IngredientConvert implements AttributeConverter<Map<String, Map<String, Map<String, BigDecimal>>>,String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(Map<String, Map<String, Map<String, BigDecimal>>> stringMapMap) { |
||||
|
return JSON.toJSONString(stringMapMap); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Map<String, Map<String, BigDecimal>>> convertToEntityAttribute(String s) { |
||||
|
return JSON.parseObject(s, new TypeReference<Map<String, Map<String, Map<String, BigDecimal>>>>(){}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.mathvision.diet.domian.MarkType; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class MarkTypeConvert implements AttributeConverter<MarkType,String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(MarkType type) { |
||||
|
return type == null ? null : type.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public MarkType convertToEntityAttribute(String s) { |
||||
|
return MarkType.toType(s); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.alibaba.fastjson2.TypeReference; |
||||
|
import com.mathvision.diet.domian.DishItemDTO; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Converter |
||||
|
public class MenuDishConvert implements AttributeConverter<Map<String, List<DishItemDTO>>, String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(Map<String, List<DishItemDTO>> stringList) { |
||||
|
return JSON.toJSONString(stringList); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, List<DishItemDTO>> convertToEntityAttribute(String s) { |
||||
|
return JSON.parseObject(s, new TypeReference<Map<String, List<DishItemDTO>>>(){}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.mathvision.diet.domian.MenuStatus; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class MenuStatusConvert implements AttributeConverter<MenuStatus, Integer> { |
||||
|
@Override |
||||
|
public Integer convertToDatabaseColumn(MenuStatus type) { |
||||
|
return type == null ? null : type.getCode(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public MenuStatus convertToEntityAttribute(Integer s) { |
||||
|
return MenuStatus.toType(s); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.mathvision.diet.domian.RoleType; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class RoleTypeConvert implements AttributeConverter<RoleType,String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(RoleType type) { |
||||
|
return type == null ? null : type.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public RoleType convertToEntityAttribute(String s) { |
||||
|
return RoleType.toType(s); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONArray; |
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.mathvision.diet.domian.RuleItemDTO; |
||||
|
|
||||
|
import javax.persistence.Converter; |
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class RuleItemConvert implements AttributeConverter<List<RuleItemDTO>, String> { |
||||
|
|
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(List<RuleItemDTO> ruleItemDTO) { |
||||
|
return JSON.toJSONString(ruleItemDTO); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<RuleItemDTO> convertToEntityAttribute(String string) { |
||||
|
return JSONArray.parseArray(string, RuleItemDTO.class); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.convert; |
||||
|
|
||||
|
import com.mathvision.diet.domian.VenderType; |
||||
|
|
||||
|
import javax.persistence.AttributeConverter; |
||||
|
import javax.persistence.Converter; |
||||
|
|
||||
|
@Converter(autoApply = true) |
||||
|
public class VenderTypeConvert implements AttributeConverter<VenderType,String> { |
||||
|
@Override |
||||
|
public String convertToDatabaseColumn(VenderType type) { |
||||
|
return type == null ? null : type.getType(); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public VenderType convertToEntityAttribute(String s) { |
||||
|
return VenderType.toType(s); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum AuthType { |
||||
|
SERVER("管理端"), CLIENT("业务端"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
AuthType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static AuthType toType(String s) { |
||||
|
return Arrays.stream(AuthType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,5 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
public enum ClientType { |
||||
|
IOS, Android, WEB |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.*; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@EqualsAndHashCode |
||||
|
@Getter |
||||
|
@Setter |
||||
|
public class DishItemDTO { |
||||
|
private String key; |
||||
|
private BigDecimal value; |
||||
|
private Boolean isMain; |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum GenderType { |
||||
|
F("女"), M("男"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
GenderType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static GenderType toType(String s) { |
||||
|
return Arrays.stream(GenderType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.Column; |
||||
|
import javax.persistence.Entity; |
||||
|
import javax.persistence.Id; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
public class IngredientDTO { |
||||
|
@Id |
||||
|
private String key; |
||||
|
private String name; |
||||
|
private String type; |
||||
|
private String mark; |
||||
|
private Instant modify; |
||||
|
@Type(type = "json") |
||||
|
@Column(columnDefinition = "json", nullable = false) |
||||
|
private Map<String, BigDecimal> nutrient; |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum MarkType { |
||||
|
frequent("常用"), forbidden("忌用"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
MarkType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static MarkType toType(String s) { |
||||
|
return Arrays.stream(MarkType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum MealType { |
||||
|
breakfast("早餐"), lunch("午餐"), dinner("晚餐"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
MealType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static MealType toType(String s) { |
||||
|
return Arrays.stream(MealType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum MeasurementType { |
||||
|
weight("克"), quantity("种"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
MeasurementType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static MeasurementType toType(String s) { |
||||
|
return Arrays.stream(MeasurementType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.MenuStatusConvert; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.Column; |
||||
|
import javax.persistence.Convert; |
||||
|
|
||||
|
@Builder |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@EqualsAndHashCode |
||||
|
public class MenuCountDTO { |
||||
|
|
||||
|
public MenuCountDTO(MenuStatus status, Long count) { |
||||
|
setCount(count); |
||||
|
setStatus(status); |
||||
|
} |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingOrdinal }) |
||||
|
@Convert(converter = MenuStatusConvert.class) |
||||
|
@Column(name = "status") |
||||
|
private MenuStatus status; |
||||
|
|
||||
|
@Column(name = "count") |
||||
|
private Long count; |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.*; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@EqualsAndHashCode |
||||
|
public class MenuDishItemDTO { |
||||
|
/** |
||||
|
* 食材 |
||||
|
*/ |
||||
|
String key; |
||||
|
|
||||
|
/** |
||||
|
* 是否主料 |
||||
|
*/ |
||||
|
Boolean isMain; |
||||
|
/** |
||||
|
* 人群列表: |
||||
|
*/ |
||||
|
Map<String, BigDecimal> value; |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum MenuStatus { |
||||
|
//0-草稿,1-提交审核,2-审核通过,3-审核失败,4-禁用,5-发布
|
||||
|
draft(0, "草稿"), publish(5, "发布"), |
||||
|
//submit(1,"审核中"), pass(2,"审核通过"), reject(3, "审核失败"), disabled(4, "禁用")
|
||||
|
; |
||||
|
|
||||
|
@Getter |
||||
|
private final int code; |
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
MenuStatus(int code, String type) { |
||||
|
this.code = code; |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static MenuStatus toType(Integer s) { |
||||
|
return Arrays.stream(MenuStatus.values()).filter(x -> s != null && x.getCode() == s).findFirst().orElse(null); |
||||
|
} |
||||
|
|
||||
|
public static MenuStatus toType(Long s) { |
||||
|
return Arrays.stream(MenuStatus.values()).filter(x -> s != null && x.getCode() == s.intValue()).findFirst().orElse(null); |
||||
|
} |
||||
|
|
||||
|
public static MenuStatus toType(String s) { |
||||
|
return Arrays.stream(MenuStatus.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
public enum MessageType { |
||||
|
CODE, NOTIFY, MESSAGE |
||||
|
} |
||||
@ -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<String, Integer> 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<String> 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<JSONObject> 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); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum RoleType { |
||||
|
SYSTEM("系统"), CUSTOM("自定义"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
RoleType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static RoleType toType(String s) { |
||||
|
return Arrays.stream(RoleType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.*; |
||||
|
import org.apache.commons.collections4.CollectionUtils; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@EqualsAndHashCode |
||||
|
public class RuleItemDTO { |
||||
|
/** |
||||
|
* 规则名称 |
||||
|
*/ |
||||
|
String name; |
||||
|
/** |
||||
|
* 计量单位 |
||||
|
*/ |
||||
|
MeasurementType type; |
||||
|
/** |
||||
|
* 食材种类 |
||||
|
*/ |
||||
|
List<String> category; |
||||
|
/** |
||||
|
* 最大值 |
||||
|
*/ |
||||
|
BigDecimal max; |
||||
|
/** |
||||
|
* 最小值 |
||||
|
*/ |
||||
|
BigDecimal min; |
||||
|
|
||||
|
public String getRange() { |
||||
|
if (max == null) return "≥" + min; |
||||
|
if (min == null) return "≤" + max; |
||||
|
return min + "~" + max; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getLack(BigDecimal num) { |
||||
|
if (max == null) return min.compareTo(num) > 0 ? min.subtract(num) : BigDecimal.ZERO; |
||||
|
if (min == null) return max.compareTo(num) > 0 ? BigDecimal.ZERO : max.subtract(num); |
||||
|
return min.compareTo(num) > 0 ? min.subtract(num) : max.compareTo(num) > 0 ? BigDecimal.ZERO : max.subtract(num); |
||||
|
} |
||||
|
|
||||
|
public boolean check() { |
||||
|
if(max != null && min != null && max.compareTo(min) < 0) { |
||||
|
BigDecimal temp = max; |
||||
|
max = min; |
||||
|
min = temp; |
||||
|
} |
||||
|
return StringUtils.isNotBlank(name) && type != null && CollectionUtils.isNotEmpty(category) && (max != null && min == null || max == null && min != null || max != null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
package com.mathvision.diet.domian; |
||||
|
|
||||
|
import lombok.Getter; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
|
||||
|
public enum VenderType { |
||||
|
school("学校"), hospital("医院"), institution("事业单位"), other("其他"); |
||||
|
|
||||
|
@Getter |
||||
|
private final String type; |
||||
|
|
||||
|
VenderType(String type) { |
||||
|
this.type = type; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
public static VenderType toType(String s) { |
||||
|
return Arrays.stream(VenderType.values()).filter(x -> x.getType().equals(s)).findFirst().orElse(null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,76 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.DishItemConvert; |
||||
|
import com.mathvision.diet.domian.DishItemDTO; |
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = "dish") |
||||
|
public class Dish { |
||||
|
|
||||
|
public Dish(Long id, String name, String marks, String poly, List<DishItemDTO> ingredient) { |
||||
|
setId(id); |
||||
|
setName(name); |
||||
|
setPoly(poly); |
||||
|
setMarks(marks); |
||||
|
setIngredient(ingredient); |
||||
|
} |
||||
|
|
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 20) |
||||
|
private String name; |
||||
|
|
||||
|
@Column(name = "`vender`", nullable = false, length = 20) |
||||
|
private Long vender; |
||||
|
|
||||
|
@Column(name = "icon") |
||||
|
private String icon; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "month", columnDefinition = "json", nullable = false) |
||||
|
private List<Integer> month; |
||||
|
|
||||
|
@Convert(converter = DishItemConvert.class) |
||||
|
@Column(name = "ingredient", columnDefinition = "json", nullable = false) |
||||
|
private List<DishItemDTO> ingredient; |
||||
|
|
||||
|
@Column(name = "marks", nullable = false, length = 45) |
||||
|
private String marks; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "label", columnDefinition = "json") |
||||
|
private List<String> label; |
||||
|
|
||||
|
@Column(name = "poly", nullable = false, length = 16) |
||||
|
private String poly; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "food_category") |
||||
|
public class FoodCategory { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "`key`", nullable = false, length = 32) |
||||
|
private String key; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 32) |
||||
|
private String value; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "food_mark") |
||||
|
public class FoodMark { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "`key`", nullable = false, length = 20) |
||||
|
private String key; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 20) |
||||
|
private String value; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "food_nutrient") |
||||
|
public class FoodNutrient { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "`key`", nullable = false, length = 20) |
||||
|
private String key; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 64) |
||||
|
private String value; |
||||
|
|
||||
|
@Column(name = "measurement", nullable = false, length = 10) |
||||
|
private String measurement; |
||||
|
|
||||
|
@Column(name = "nrv", nullable = false, precision = 5, scale = 2) |
||||
|
private BigDecimal nrv; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "food_poly") |
||||
|
public class FoodPoly { |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "`key`", nullable = false, length = 20) |
||||
|
private String key; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 20) |
||||
|
private String name; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = "ingredient", schema = "diet") |
||||
|
public class Ingredient { |
||||
|
public Ingredient(String key, String name) { |
||||
|
setKey(key); |
||||
|
setName(name); |
||||
|
} |
||||
|
|
||||
|
public Ingredient(String key, String name, String type) { |
||||
|
setKey(key); |
||||
|
setName(name); |
||||
|
setType(type); |
||||
|
} |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "`key`", nullable = false, length = 20) |
||||
|
private String key; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 64) |
||||
|
private String name; |
||||
|
|
||||
|
@Column(name = "type", nullable = false, length = 64) |
||||
|
private String type; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "nutrient", columnDefinition = "json", nullable = false) |
||||
|
private Map<String, BigDecimal> nutrient; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.MarkTypeConvert; |
||||
|
import com.mathvision.diet.domian.MarkType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "ingredient_mark", schema = "diet") |
||||
|
public class IngredientMark { |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "ingredient", nullable = false, length = 20) |
||||
|
private String ingredient; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingToString }) |
||||
|
@Convert(converter = MarkTypeConvert.class) |
||||
|
@Column(name = "mark", columnDefinition="ENUM('常用','忌用')", nullable = false) |
||||
|
private MarkType mark; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,95 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.MenuStatusConvert; |
||||
|
import com.mathvision.diet.domian.MenuStatus; |
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = "menu") |
||||
|
public class Menu { |
||||
|
|
||||
|
public Menu(Long id, String name) { |
||||
|
setId(id); |
||||
|
setName(name); |
||||
|
} |
||||
|
|
||||
|
public Menu(Long id, String name, List<Long> day) { |
||||
|
setId(id); |
||||
|
setName(name); |
||||
|
setDay(day); |
||||
|
} |
||||
|
|
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@Column(name = "nutrient", nullable = false) |
||||
|
private Long nutrient; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 20) |
||||
|
private String name; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "day", columnDefinition = "json", nullable = false) |
||||
|
private List<Long> day; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "meals", columnDefinition = "json", nullable = false) |
||||
|
private List<String> meals; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "crows", columnDefinition = "json", nullable = false) |
||||
|
private List<String> crows; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "scale", columnDefinition = "json", nullable = false) |
||||
|
private Map<String, Integer> scale; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "month", columnDefinition = "json", nullable = false) |
||||
|
private List<Integer> month; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingOrdinal }) |
||||
|
@Convert(converter = MenuStatusConvert.class) |
||||
|
@Column(name = "status", columnDefinition = "tinyint UNSIGNED not null") |
||||
|
private MenuStatus status; |
||||
|
|
||||
|
@Column(name = "approve") |
||||
|
private String approve; |
||||
|
|
||||
|
@Column(name = "start_time") |
||||
|
private Instant startTime; |
||||
|
|
||||
|
@Column(name = "end_time") |
||||
|
private Instant endTime; |
||||
|
|
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "menu_approve") |
||||
|
public class MenuApprove { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "menu", nullable = false) |
||||
|
private Long menu; |
||||
|
|
||||
|
@Column(name = "approve", length = 16) |
||||
|
private String approve; |
||||
|
|
||||
|
@Column(name = "pass", nullable = false) |
||||
|
private Boolean pass = false; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,72 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.domian.MenuDishItemDTO; |
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = "menu_dish") |
||||
|
public class MenuDish { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@Column(name = "menu", nullable = false) |
||||
|
private Long menu; |
||||
|
|
||||
|
@Column(name = "day", columnDefinition = "int UNSIGNED not null") |
||||
|
private Long day; |
||||
|
|
||||
|
@Column(name = "meal", nullable = false, length = 16) |
||||
|
private String meal; |
||||
|
|
||||
|
@Column(name = "dish", nullable = false) |
||||
|
private Long dish; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 64) |
||||
|
private String name; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "ingredient", columnDefinition = "json", nullable = false) |
||||
|
private List<MenuDishItemDTO> ingredient; |
||||
|
|
||||
|
@Column(name = "marks", nullable = false, length = 45) |
||||
|
private String marks; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "label", columnDefinition = "json") |
||||
|
private List<String> label; |
||||
|
|
||||
|
@Column(name = "poly", nullable = false, length = 16) |
||||
|
private String poly; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.IngredientConvert; |
||||
|
import com.mathvision.diet.convert.RuleItemConvert; |
||||
|
import com.mathvision.diet.domian.RuleItemDTO; |
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = "nutrition", schema = "diet") |
||||
|
public class Nutrition { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 20) |
||||
|
private String name; |
||||
|
|
||||
|
@Type( type = "json" ) |
||||
|
@Column(name = "vendors", columnDefinition = "json", nullable = false) |
||||
|
private List<Long> vendors; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "crows", columnDefinition = "json") |
||||
|
private List<String> crows; |
||||
|
|
||||
|
@Convert(converter = RuleItemConvert.class) |
||||
|
@Column(name = "food_category_day", columnDefinition = "json") |
||||
|
private List<RuleItemDTO> foodCategoryDay; |
||||
|
|
||||
|
@Convert(converter = RuleItemConvert.class) |
||||
|
@Column(name = "food_category_week", columnDefinition = "json") |
||||
|
private List<RuleItemDTO> foodCategoryWeek; |
||||
|
|
||||
|
@Convert(converter = IngredientConvert.class) |
||||
|
@Column(name = "ingredient", columnDefinition = "json") |
||||
|
private Map<String, Map<String, Map<String, BigDecimal>>> ingredient; |
||||
|
|
||||
|
@Column(name = "overflow", nullable = false, precision = 5, scale = 2) |
||||
|
private BigDecimal overflow; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "overflows", columnDefinition = "json") |
||||
|
private Map<String, BigDecimal> overflows; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.RoleTypeConvert; |
||||
|
import com.mathvision.diet.domian.RoleType; |
||||
|
import com.vladmihalcea.hibernate.type.json.JsonStringType; |
||||
|
import lombok.*; |
||||
|
import org.hibernate.annotations.Type; |
||||
|
import org.hibernate.annotations.TypeDef; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
import java.util.List; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@TypeDef(name = "json", typeClass = JsonStringType.class) |
||||
|
@Table(name = "role") |
||||
|
public class Role { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "role_name", nullable = false, length = 45) |
||||
|
private String roleName; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingToString }) |
||||
|
@Convert(converter = RoleTypeConvert.class) |
||||
|
@Column(name = "role_type", columnDefinition="ENUM('系统','自定义')", nullable = false) |
||||
|
private RoleType roleType; |
||||
|
|
||||
|
@Type(type = "json") |
||||
|
@Column(name = "role_items", columnDefinition = "json", nullable = false) |
||||
|
private List<Long> roleItems; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.AuthTypeConvert; |
||||
|
import com.mathvision.diet.domian.AuthType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "role_item") |
||||
|
public class RoleItem { |
||||
|
|
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "item_name", nullable = false, length = 45) |
||||
|
private String itemName; |
||||
|
|
||||
|
@Column(name = "category", nullable = false, length = 50) |
||||
|
private String category; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingToString }) |
||||
|
@Convert(converter = AuthTypeConvert.class) |
||||
|
@Column(name = "item_type", columnDefinition="ENUM('管理端','业务端')", nullable = false) |
||||
|
private AuthType itemType; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "item_value", nullable = false) |
||||
|
private String itemValue; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
import java.time.LocalDate; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "sugar") |
||||
|
public class Sugar { |
||||
|
|
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 64) |
||||
|
private String name; |
||||
|
|
||||
|
@Column(name = "day", columnDefinition = "int UNSIGNED not null") |
||||
|
private Integer day; |
||||
|
|
||||
|
@Column(name = "sugar_day", precision = 10, scale = 2) |
||||
|
private BigDecimal sugarDay; |
||||
|
|
||||
|
@Column(name = "sugar_week", precision = 10, scale = 2) |
||||
|
private BigDecimal sugarWeek; |
||||
|
|
||||
|
@Column(name = "oil_day", precision = 10, scale = 2) |
||||
|
private BigDecimal oilDay; |
||||
|
|
||||
|
@Column(name = "oil_week", precision = 10, scale = 2) |
||||
|
private BigDecimal oilWeek; |
||||
|
|
||||
|
@Column(name = "salt_day", precision = 10, scale = 2) |
||||
|
private BigDecimal saltDay; |
||||
|
|
||||
|
@Column(name = "salt_week", precision = 10, scale = 2) |
||||
|
private BigDecimal saltWeek; |
||||
|
|
||||
|
@Column(name = "start_time") |
||||
|
private LocalDate startTime; |
||||
|
|
||||
|
@Column(name = "end_time") |
||||
|
private LocalDate endTime; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.GenderTypeConvert; |
||||
|
import com.mathvision.diet.domian.GenderType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "user") |
||||
|
public class User { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "uid", nullable = false, length = 16) |
||||
|
private String uid; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "pwd", nullable = false, length = 16) |
||||
|
private String pwd; |
||||
|
|
||||
|
@Column(name = "status", nullable = false) |
||||
|
private Boolean status = false; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 64) |
||||
|
private String name; |
||||
|
|
||||
|
@Column(name = "phone", length = 16) |
||||
|
private String phone; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingToString }) |
||||
|
@Convert(converter = GenderTypeConvert.class) |
||||
|
@Column(name = "gender", columnDefinition="ENUM('男','女')") |
||||
|
private GenderType gender; |
||||
|
|
||||
|
@Column(name = "email", length = 64) |
||||
|
private String email; |
||||
|
|
||||
|
@Column(name = "address", length = 64) |
||||
|
private String address; |
||||
|
|
||||
|
@Column(name = "flag") |
||||
|
private Boolean flag; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.domian.ClientType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "user_log") |
||||
|
public class UserLog { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "uid", nullable = false, length = 18) |
||||
|
private String uid; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumsUsingName }) |
||||
|
@Enumerated(EnumType.STRING) |
||||
|
@Column(name = "client_type", columnDefinition="ENUM('web','android','ios')", nullable = false) |
||||
|
private ClientType clientType; |
||||
|
|
||||
|
@Column(name = "client_version", nullable = false) |
||||
|
private String clientVersion; |
||||
|
|
||||
|
@Column(name = "login", nullable = false) |
||||
|
private Instant login; |
||||
|
|
||||
|
@Column(name = "logout") |
||||
|
private Instant logout; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.domian.MessageType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "user_message") |
||||
|
public class UserMessage { |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "uid", nullable = false, length = 45) |
||||
|
private String uid; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumsUsingName }) |
||||
|
@Enumerated(EnumType.STRING) |
||||
|
@Column(name = "type", columnDefinition="ENUM('code','notify','message')", nullable = false) |
||||
|
private MessageType type; |
||||
|
|
||||
|
@Column(name = "content", nullable = false, length = 128) |
||||
|
private String content; |
||||
|
|
||||
|
@Column(name = "status", nullable = false) |
||||
|
private Boolean status = false; |
||||
|
|
||||
|
@Column(name = "operate", length = 18) |
||||
|
private String operate; |
||||
|
|
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "user_role") |
||||
|
public class UserRole { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "uid", nullable = false, length = 18) |
||||
|
private String uid; |
||||
|
|
||||
|
@Column(name = "role_id", columnDefinition = "int UNSIGNED not null") |
||||
|
private Long roleId; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.domian.ClientType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "user_session") |
||||
|
public class UserSession { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "uid", nullable = false, length = 18) |
||||
|
private String uid; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false, length = 64) |
||||
|
private String vender; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumsUsingName }) |
||||
|
@Enumerated(EnumType.STRING) |
||||
|
@Column(name = "client_type", columnDefinition="ENUM('web','android','ios')", nullable = false) |
||||
|
private ClientType clientType; |
||||
|
|
||||
|
@Column(name = "client_version", nullable = false, length = 45) |
||||
|
private String clientVersion; |
||||
|
|
||||
|
@Column(name = "expired_time", nullable = false) |
||||
|
private Long expiredTime; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,89 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSONWriter; |
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import com.mathvision.diet.convert.VenderTypeConvert; |
||||
|
import com.mathvision.diet.domian.VenderType; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "vender") |
||||
|
public class Vender { |
||||
|
|
||||
|
public Vender (Long id, String name, String account, VenderType category) { |
||||
|
setId(id); |
||||
|
setAccount(account); |
||||
|
setName(name); |
||||
|
setCategory(category); |
||||
|
} |
||||
|
|
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "account", length = 16, nullable = false) |
||||
|
private String account; |
||||
|
|
||||
|
@Column(name = "name", nullable = false, length = 64) |
||||
|
private String name; |
||||
|
|
||||
|
@JSONField(serializeFeatures = { JSONWriter.Feature.WriteEnumUsingToString }) |
||||
|
@Convert(converter = VenderTypeConvert.class) |
||||
|
@Column(name = "category", columnDefinition="ENUM('学校','医院','事业单位','其他')") |
||||
|
private VenderType category; |
||||
|
|
||||
|
@Column(name = "status", nullable = false) |
||||
|
private Boolean status; |
||||
|
|
||||
|
@Column(name = "icon") |
||||
|
private String icon; |
||||
|
|
||||
|
@Column(name = "url", length = 64) |
||||
|
private String url; |
||||
|
|
||||
|
@Column(name = "province", length = 20) |
||||
|
private String province; |
||||
|
|
||||
|
@Column(name = "city", length = 20) |
||||
|
private String city; |
||||
|
|
||||
|
@Column(name = "area", length = 20) |
||||
|
private String area; |
||||
|
|
||||
|
@Column(name = "address", length = 64) |
||||
|
private String address; |
||||
|
|
||||
|
@Column(name = "phone", length = 16) |
||||
|
private String phone; |
||||
|
|
||||
|
@Column(name = "contacts", length = 16) |
||||
|
private String contacts; |
||||
|
|
||||
|
@Column(name = "email", length = 32) |
||||
|
private String email; |
||||
|
|
||||
|
@Column(name = "expire") |
||||
|
private Instant expire; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 18) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
package com.mathvision.diet.entity; |
||||
|
|
||||
|
import com.alibaba.fastjson2.annotation.JSONField; |
||||
|
import lombok.*; |
||||
|
|
||||
|
import javax.persistence.*; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@Builder |
||||
|
@AllArgsConstructor |
||||
|
@NoArgsConstructor |
||||
|
@Getter |
||||
|
@Setter |
||||
|
@Entity |
||||
|
@Table(name = "vender_config") |
||||
|
public class VenderConfig { |
||||
|
@JSONField(serialize = false) |
||||
|
@Id |
||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY) |
||||
|
@Column(name = "id", nullable = false) |
||||
|
private Long id; |
||||
|
|
||||
|
@Column(name = "vender", nullable = false) |
||||
|
private Long vender; |
||||
|
|
||||
|
@JSONField(format = "#0.00") |
||||
|
@Column(name = "breakfast", precision = 5, scale = 2) |
||||
|
private BigDecimal breakfast; |
||||
|
|
||||
|
@JSONField(format = "#0.00") |
||||
|
@Column(name = "lunch", precision = 5, scale = 2) |
||||
|
private BigDecimal lunch; |
||||
|
|
||||
|
@JSONField(format = "#0.00") |
||||
|
@Column(name = "dinner", precision = 5, scale = 2) |
||||
|
private BigDecimal dinner; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "operate", length = 45) |
||||
|
private String operate; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "created") |
||||
|
private Instant created; |
||||
|
|
||||
|
@JSONField(serialize = false) |
||||
|
@Column(name = "modify") |
||||
|
private Instant modify; |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.Dish; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.time.Instant; |
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface DishRepository extends JpaRepository<Dish, Long>, JpaSpecificationExecutor<Dish> { |
||||
|
List<Dish> findByModifyGreaterThan(Instant modify); |
||||
|
@Transactional |
||||
|
long deleteByVender(Long vender); |
||||
|
@Query("select new Dish(d.id, d.name, d.marks, d.poly, d.ingredient) from Dish d where d.name like ?1 order by d.id DESC") |
||||
|
List<Dish> findByNameLikeOrderByIdDesc(String name); |
||||
|
boolean existsByVenderAndNameAndIdNot(Long vender, String name, Long id); |
||||
|
boolean existsByVenderAndIdIn(Long vender, Collection<Long> ids); |
||||
|
@Transactional |
||||
|
long deleteByIdInAndVender(Collection<Long> ids, Long vender); |
||||
|
@Query("select d from Dish d where d.vender = ?1 and d.id in ?2") |
||||
|
List<Dish> findByVenderAndIdIn(Long vender, Collection<Long> ids); |
||||
|
@Query("select d from Dish d where d.id in ?1") |
||||
|
List<Dish> findByIdIn(Collection<Long> ids); |
||||
|
@Query("select d from Dish d where d.vender = ?1") |
||||
|
List<Dish> findByVender(Long vender); |
||||
|
@Query("select count(d) from Dish d where d.vender = ?1") |
||||
|
long countByVender(Long vender); |
||||
|
Dish findByIdAndVender(Long id, Long vender); |
||||
|
boolean existsByVenderAndName(Long vender, String name); |
||||
|
List<Dish> findByVenderAndName(Long vender, String name); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.FoodCategory; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
public interface FoodCategoryRepository extends JpaRepository<FoodCategory, Long>, JpaSpecificationExecutor<FoodCategory> { |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.FoodMark; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
public interface FoodMarkRepository extends JpaRepository<FoodMark, Long>, JpaSpecificationExecutor<FoodMark> { |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.FoodNutrient; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
public interface FoodNutrientRepository extends JpaRepository<FoodNutrient, Long>, JpaSpecificationExecutor<FoodNutrient> { |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.FoodPoly; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
public interface FoodPolyRepository extends JpaRepository<FoodPoly, Long>, JpaSpecificationExecutor<FoodPoly> { |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.domian.IngredientDTO; |
||||
|
import com.mathvision.diet.entity.IngredientMark; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
|
||||
|
public interface IngredientDTORepository extends JpaRepository<IngredientDTO, String> , JpaSpecificationExecutor<IngredientMark> { |
||||
|
@Query(countQuery = "SELECT count(1) FROM ingredient a left join (select ingredient as `key`, mark from ingredient_mark where vender = ?1) b on a.key = b.key where 1=1 and if(IFNULL(?2,'') ='', 1=1, a.type = ?2) and if(IFNULL(?3,'') ='', 1=1, b.mark = ?3) and if(IFNULL(?4,'') ='', 1=1, (a.key like concat('%', ?4, '%') or a.name like concat('%', ?4, '%') ))", |
||||
|
value = "SELECT a.key, a.name, a.type, a.nutrient, b.mark, a.modify FROM ingredient a left join (select ingredient as `key`, mark from ingredient_mark where vender = ?1) b on a.key = b.key where 1=1 and if(IFNULL(?2,'') ='', 1=1, a.type = ?2) and if(IFNULL(?3,'') ='', 1=1, b.mark = ?3) and if(IFNULL(?4,'') ='', 1=1, (a.key like concat('%', ?4, '%') or a.name like concat('%', ?4, '%') )) order by a.id DESC", nativeQuery = true) |
||||
|
Page<IngredientDTO> findByVenderAndTypeAndMarkAndKey(Long vender, String type, String mark, String key, Pageable pageable); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.domian.MarkType; |
||||
|
import com.mathvision.diet.entity.IngredientMark; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
public interface IngredientMarkRepository extends JpaRepository<IngredientMark, Long>, JpaSpecificationExecutor<IngredientMark> { |
||||
|
@Transactional |
||||
|
long deleteByIngredient(String ingredient); |
||||
|
|
||||
|
@Transactional |
||||
|
long deleteByVender(Long vender); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update IngredientMark i set i.mark = ?1, i.operate = ?2 where i.vender = ?3 and i.ingredient = ?4") |
||||
|
int updateMarkAndOperateByVenderAndIngredient(MarkType mark, String operate, Long vender, String ingredient); |
||||
|
@Transactional |
||||
|
long deleteByVenderAndIngredient(Long vender, String ingredient); |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.Ingredient; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface IngredientRepository extends JpaRepository<Ingredient, Long>, JpaSpecificationExecutor<Ingredient> { |
||||
|
@Query("select new Ingredient(i.key,i.name,i.type) from Ingredient i where i.key like concat('%', ?1, '%') or i.name like concat('%', ?1, '%') order by i.key") |
||||
|
List<Ingredient> findByKeyLikeOrNameLikeOrderByKeyAsc(String keyword); |
||||
|
@Query("select new Ingredient(i.key,i.name,i.type) from Ingredient i where i.key in ?1 order by i.key") |
||||
|
List<Ingredient> findByKeyInOrderByKeyAsc(Collection<String> keys); |
||||
|
@Query("select new Ingredient(i.key,i.name) from Ingredient i") |
||||
|
List<Ingredient> findKeyNameMap(); |
||||
|
|
||||
|
@Query("select i from Ingredient i where i.key in ?1") |
||||
|
List<Ingredient> findByKeyIn(Collection<String> keys); |
||||
|
boolean existsByKey(String key); |
||||
|
@Transactional |
||||
|
long deleteByKey(String key); |
||||
|
Ingredient findByKey(String key); |
||||
|
|
||||
|
Page<Ingredient> findByTypeOrderByIdDesc(String type, Pageable pageable); |
||||
|
|
||||
|
Page<Ingredient> findByKeyLikeOrderByIdDesc(String key, Pageable pageable); |
||||
|
|
||||
|
Page<Ingredient> findByNameLikeOrderByIdDesc(String name, Pageable pageable); |
||||
|
|
||||
|
Page<Ingredient> findByTypeAndKeyLikeOrderByIdDesc(String type, String key, Pageable pageable); |
||||
|
|
||||
|
Page<Ingredient> findByTypeAndNameLikeOrderByIdDesc(String type, String name, Pageable pageable); |
||||
|
|
||||
|
@Query("select (count(i) > 0) from Ingredient i where i.id <> ?1 and (i.key = ?2 or i.name = ?3)") |
||||
|
boolean existsByIdNotAndKeyOrName(Long id, String key, String name); |
||||
|
boolean existsByKeyOrName(String key, String name); |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.MenuApprove; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
public interface MenuApproveRepository extends JpaRepository<MenuApprove, Long>, JpaSpecificationExecutor<MenuApprove> { |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("delete from MenuApprove m where DATEDIFF(NOW(), m.modify) > 30") |
||||
|
void scanExpired(); |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.MenuDish; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.time.Instant; |
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface MenuDishRepository extends JpaRepository<MenuDish, Long>, JpaSpecificationExecutor<MenuDish> { |
||||
|
boolean existsByMenuAndDay(Long menu, Long day); |
||||
|
boolean existsByMenu(Long menu); |
||||
|
@Transactional |
||||
|
long deleteByVender(Long vender); |
||||
|
List<MenuDish> findByMenuAndVenderAndDay(Long menu, Long vender, Long day); |
||||
|
List<MenuDish> findByMenuAndVender(Long menu, Long vender); |
||||
|
MenuDish findByIdAndVender(Long id, Long vender); |
||||
|
List<MenuDish> findByMenu(Long menu); |
||||
|
@Transactional |
||||
|
long deleteByMenuAndDayNotInAndMealNotIn(Long menu, Collection<Long> day, Collection<String> meals); |
||||
|
@Transactional |
||||
|
long deleteByMenuAndVender(Long menu, Long vender); |
||||
|
@Transactional |
||||
|
long deleteByMenu(Long menu); |
||||
|
@Transactional |
||||
|
long deleteByDishInAndVender(Collection<Long> ids, Long vender); |
||||
|
@Transactional |
||||
|
long deleteByDishIn(Collection<Long> ids); |
||||
|
|
||||
|
List<MenuDish> findByModifyGreaterThan(Instant updateLabelTime); |
||||
|
|
||||
|
@Query("select distinct d.day from MenuDish d where d.menu=?1 and d.vender = ?2") |
||||
|
List<Long> distinctDaysByMenuAndVender(Long id, Long name); |
||||
|
} |
||||
@ -0,0 +1,59 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.domian.MenuCountDTO; |
||||
|
import com.mathvision.diet.domian.MenuStatus; |
||||
|
import com.mathvision.diet.entity.Menu; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.time.Instant; |
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
public interface MenuRepository extends JpaRepository<Menu, Long>, JpaSpecificationExecutor<Menu> { |
||||
|
List<Menu> findByNutrient(Long nutrient); |
||||
|
@Transactional |
||||
|
long deleteByVender(Long vender); |
||||
|
|
||||
|
@Query(value = "select new Menu(m.id, m.name) from Menu m " + |
||||
|
"where m.vender = ?1 and m.status = 5 and now() between m.startTime and m.endTime") |
||||
|
List<Menu> findCurrentMenu(Long vender); |
||||
|
|
||||
|
@Query(value = "select m from Menu m " + |
||||
|
"where m.vender = ?1 and m.status = 5 and YEAR(now()) * 100 + WEEK(now()) between YEAR(m.startTime) * 100 + WEEK(m.startTime) and YEAR(m.endTime) * 100 + WEEK(m.endTime)") |
||||
|
List<Menu> findCurrentWeekMenu(Long vender); |
||||
|
|
||||
|
@Query("select new com.mathvision.diet.domian.MenuCountDTO(m.status, count(m)) from Menu m where m.status in ?1 group by m.status") |
||||
|
List<MenuCountDTO> count(Collection<MenuStatus> statuses); |
||||
|
@Query("select count(m) from Menu m where m.vender = ?1") |
||||
|
long countByVender(Long vender); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Menu m set m.status = ?1, m.scale = ?2, m.startTime = ?3, m.endTime = ?4 where m.id = ?5") |
||||
|
int updateStatusAndScaleAndStartTimeAndEndTimeById(MenuStatus status, Map<String, Integer> scale, Instant startTime, Instant endTime, Long id); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Menu m set m.status = ?1, m.approve = ?2, m.operate = ?3 where m.id = ?4") |
||||
|
int updateStatusAndApproveAndOperateById(MenuStatus status, String approve, String operate, Long id); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Menu m set m.status = ?1, m.operate = ?2 where m.id = ?3") |
||||
|
int updateStatusAndOperateById(MenuStatus status, String operate, Long id); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Menu m set m.status = ?1, m.startTime = ?2, m.endTime = ?3, m.operate = ?4 where m.id = ?5") |
||||
|
int updateStatusAndStartTimeAndEndTimeAndOperateById(MenuStatus status, Instant startTime, Instant endTime, String operate, Long id); |
||||
|
@Transactional |
||||
|
long deleteByIdAndVender(Long id, Long vender); |
||||
|
|
||||
|
Menu findByIdAndVender(Long id, Long vender); |
||||
|
|
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query(value = "update menu v set v.status = 0 where v.status = 5 and v.end_time < now()", nativeQuery = true) |
||||
|
void scanExpired(); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.Nutrition; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface NutritionRepository extends JpaRepository<Nutrition, Long>, JpaSpecificationExecutor<Nutrition> { |
||||
|
List<Nutrition> findByNameLike(String name); |
||||
|
Page<Nutrition> findByNameLikeOrderByIdDesc(String name, Pageable pageable); |
||||
|
boolean existsByName(String name); |
||||
|
Nutrition findByName(String name); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.RoleItem; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
public interface RoleItemRepository extends JpaRepository<RoleItem, Long>, JpaSpecificationExecutor<RoleItem> { |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.domian.RoleType; |
||||
|
import com.mathvision.diet.entity.Role; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> { |
||||
|
@Transactional |
||||
|
long deleteByIdAndVenderAndRoleTypeNot(Long id, Long vender, RoleType roleType); |
||||
|
@Transactional |
||||
|
long deleteByVender(Long vender); |
||||
|
|
||||
|
boolean existsByIdAndVender(Long id, Long vender); |
||||
|
|
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Role r set r.roleItems = ?1, r.operate = ?2 where r.id = ?3 and r.vender = ?4 and r.roleType != '系统'") |
||||
|
int updateRoleItemsAndOperateByIdAndVenderAndRoleTypeNot(String roleItems, String operate, Long id, Long vender); |
||||
|
|
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Role r set r.roleName = ?1, r.operate = ?2 where r.id = ?3 and r.vender = ?4 and r.roleType != '系统'") |
||||
|
int updateRoleNameAndOperateByIdAndVenderAndRoleTypeNot(String roleName, String operate, Long id, Long vender); |
||||
|
|
||||
|
List<Role> findByVender(Long vender); |
||||
|
|
||||
|
@Query("SELECT d FROM Role d WHERE d.vender = ?1 AND ?2= d.roleType") |
||||
|
Role findByVenderForDefaultRole(Long vender, RoleType roleType); |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.Sugar; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
|
||||
|
public interface SugarRepository extends JpaRepository<Sugar, Long>, JpaSpecificationExecutor<Sugar> { |
||||
|
long deleteByVender(Long vender); |
||||
|
boolean existsByVenderAndName(Long vender, String name); |
||||
|
Sugar findByIdAndVender(Long id, Long vender); |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.UserLog; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.lang.NonNull; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.time.Instant; |
||||
|
|
||||
|
public interface UserLogRepository extends JpaRepository<UserLog, Long>, JpaSpecificationExecutor<UserLog> { |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query(value = "update user_log u set u.logout = ?1 where u.uid = ?2 order by u.id desc limit 1", nativeQuery = true) |
||||
|
void updateLogoutByUid(@NonNull Instant logout, @NonNull String uid); |
||||
|
|
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("delete from UserLog m where DATEDIFF(NOW(), m.login) > 30") |
||||
|
void scanExpired(); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.UserMessage; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
public interface UserMessageRepository extends JpaRepository<UserMessage, Long>, JpaSpecificationExecutor<UserMessage> { |
||||
|
|
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("delete from UserMessage m where DATEDIFF(NOW(), m.modify) > 30") |
||||
|
void scanExpired(); |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.User; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { |
||||
|
@Transactional |
||||
|
long deleteByUidIn(Collection<String> uid); |
||||
|
List<User> findByUidIn(Collection<String> uid); |
||||
|
boolean existsByUidAndPwdAndStatus(String uid, String pwd, Boolean status); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update User u set u.pwd = ?1 where u.uid = ?2") |
||||
|
int updatePwdByUid(String pwd, String uid); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update User u set u.name = ?1 where u.uid = ?2") |
||||
|
int updateNameByUid(String name, String uid); |
||||
|
@Transactional |
||||
|
long deleteByUid(String uid); |
||||
|
boolean existsByUid(String uid); |
||||
|
User findByUidAndStatus(String uid, Boolean status); |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.UserRole; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface UserRoleRepository extends JpaRepository<UserRole, Long>, JpaSpecificationExecutor<UserRole> { |
||||
|
@Transactional |
||||
|
long deleteByVender(Long vender); |
||||
|
@Transactional |
||||
|
long deleteByUidAndVender(String uid, Long vender); |
||||
|
long countByRoleIdAndVenderAndUidNot(Long roleId, Long vender, String uid); |
||||
|
boolean existsByUidAndVender(String uid, Long vender); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update UserRole u set u.roleId = ?1, u.operate = ?2 where u.uid = ?3 and u.vender = ?4") |
||||
|
int updateRoleIdAndOperateByUidAndVender(Long roleId, String operate, String uid, Long vender); |
||||
|
boolean existsByRoleIdAndVender(Long roleId, Long vender); |
||||
|
List<UserRole> findByVender(Long vender); |
||||
|
UserRole findByUid(String uid); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.UserSession; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
public interface UserSessionRepository extends JpaRepository<UserSession, Long>, JpaSpecificationExecutor<UserSession> { |
||||
|
|
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("delete from UserSession m where DATEDIFF(NOW(), m.modify) > 30") |
||||
|
void scanExpired(); |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.entity.VenderConfig; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
public interface VenderConfigRepository extends JpaRepository<VenderConfig, Long>, JpaSpecificationExecutor<VenderConfig> { |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update VenderConfig v set v.breakfast = ?1, v.lunch = ?2, v.dinner = ?3, v.operate = ?4 where v.vender = ?5") |
||||
|
int updateBreakfastAndLunchAndDinnerAndOperateByVender(BigDecimal breakfast, BigDecimal lunch, BigDecimal dinner, String operate, Long vender); |
||||
|
long deleteByVender(Long vender); |
||||
|
VenderConfig findByVender(Long vender); |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
package com.mathvision.diet.repository; |
||||
|
|
||||
|
import com.mathvision.diet.domian.VenderType; |
||||
|
import com.mathvision.diet.entity.Vender; |
||||
|
import org.springframework.data.domain.Page; |
||||
|
import org.springframework.data.domain.PageRequest; |
||||
|
import org.springframework.data.domain.Pageable; |
||||
|
import org.springframework.data.jpa.repository.JpaRepository; |
||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor; |
||||
|
import org.springframework.data.jpa.repository.Modifying; |
||||
|
import org.springframework.data.jpa.repository.Query; |
||||
|
import org.springframework.transaction.annotation.Transactional; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface VenderRepository extends JpaRepository<Vender, Long>, JpaSpecificationExecutor<Vender> { |
||||
|
Page<Vender> findByCategoryAndNameLikeOrderByIdDesc(VenderType category, String name, Pageable pageable); |
||||
|
Page<Vender> findByCategoryOrderByIdDesc(VenderType category, Pageable pageable); |
||||
|
@Query("select new Vender(v.id, v.name, v.account, v.category) from Vender v where v.id in ?1") |
||||
|
List<Vender> findByIdIn(Collection<Long> ids); |
||||
|
@Query("select new Vender(v.id, v.name, v.account, v.category) from Vender v where v.status = ?1 and v.name like ?2 order by v.name DESC") |
||||
|
List<Vender> findByStatusAndNameLikeOrderByNameDesc(Boolean status, String name); |
||||
|
@Query("select new Vender(v.id, v.name, v.account, v.category) from Vender v where v.status = ?1 order by v.name") |
||||
|
List<Vender> findByStatusOrderByNameAsc(Boolean status); |
||||
|
Page<Vender> findByNameLikeOrderByIdDesc(String name, PageRequest pageRequest); |
||||
|
boolean existsByName(String name); |
||||
|
@Transactional |
||||
|
@Modifying |
||||
|
@Query("update Vender v set v.status = false where v.status = true and v.expire < now()") |
||||
|
void scanExpired(); |
||||
|
Vender findByIdAndStatus(Long vender, boolean status); |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
|
||||
|
<parent> |
||||
|
<groupId>com.mathvision.diet</groupId> |
||||
|
<artifactId>diet</artifactId> |
||||
|
<version>1.0-SNAPSHOT</version> |
||||
|
</parent> |
||||
|
<artifactId>diet-web</artifactId> |
||||
|
<packaging>jar</packaging> |
||||
|
|
||||
|
<properties> |
||||
|
<maven.compiler.source>8</maven.compiler.source> |
||||
|
<maven.compiler.target>8</maven.compiler.target> |
||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
</properties> |
||||
|
|
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-web</artifactId> |
||||
|
<exclusions> |
||||
|
<exclusion> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-starter-json</artifactId> |
||||
|
</exclusion> |
||||
|
</exclusions> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.auth0</groupId> |
||||
|
<artifactId>java-jwt</artifactId> |
||||
|
<version>4.3.0</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.mathvision.diet</groupId> |
||||
|
<artifactId>diet-core</artifactId> |
||||
|
<version>1.0-SNAPSHOT</version> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
|
||||
|
<build> |
||||
|
<resources> |
||||
|
<resource> |
||||
|
<directory>src/main/resources</directory> |
||||
|
<includes> |
||||
|
<include>*.properties</include> |
||||
|
<include>*.xml</include> |
||||
|
<include>*.yml</include> |
||||
|
<include>**/*.so</include> |
||||
|
<include>**/*.dll</include> |
||||
|
<include>static/**</include> |
||||
|
</includes> |
||||
|
</resource> |
||||
|
</resources> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.springframework.boot</groupId> |
||||
|
<artifactId>spring-boot-maven-plugin</artifactId> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
</project> |
||||
@ -0,0 +1,13 @@ |
|||||
|
package com.mathvision.diet; |
||||
|
|
||||
|
import org.springframework.boot.SpringApplication; |
||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
import org.springframework.scheduling.annotation.EnableScheduling; |
||||
|
|
||||
|
@EnableScheduling |
||||
|
@SpringBootApplication |
||||
|
public class Application { |
||||
|
public static void main(String[] args) { |
||||
|
SpringApplication.run(Application.class, args); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,79 @@ |
|||||
|
package com.mathvision.diet.aspect; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.mathvision.diet.domain.Result; |
||||
|
import com.mathvision.diet.exception.DietException; |
||||
|
import lombok.SneakyThrows; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.stereotype.Controller; |
||||
|
import org.springframework.web.bind.MissingPathVariableException; |
||||
|
import org.springframework.web.bind.MissingRequestCookieException; |
||||
|
import org.springframework.web.bind.MissingRequestHeaderException; |
||||
|
import org.springframework.web.bind.MissingServletRequestParameterException; |
||||
|
import org.springframework.web.bind.annotation.ControllerAdvice; |
||||
|
import org.springframework.web.bind.annotation.ExceptionHandler; |
||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
import org.springframework.web.context.request.RequestContextHolder; |
||||
|
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
|
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; |
||||
|
import org.springframework.web.multipart.MultipartException; |
||||
|
|
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Controller |
||||
|
@ControllerAdvice |
||||
|
public class GlobalExceptionHandler { |
||||
|
|
||||
|
@ResponseBody |
||||
|
@ExceptionHandler(DietException.class) |
||||
|
public Result errorHandler(DietException e) { |
||||
|
return _innerHandler(e.getResult(), e, false); |
||||
|
} |
||||
|
|
||||
|
@ResponseBody |
||||
|
@ExceptionHandler({IllegalArgumentException.class, IllegalStateException.class}) |
||||
|
public Result errorHandler(IllegalArgumentException e) { |
||||
|
return _innerHandler(Result.ILLEGAL_ARGUMENT, e, false); |
||||
|
} |
||||
|
|
||||
|
@ResponseBody |
||||
|
@ExceptionHandler({MissingServletRequestParameterException.class, MissingPathVariableException.class, MissingRequestCookieException.class, MissingRequestHeaderException.class, MissingServletRequestParameterException.class}) |
||||
|
public Result errorHandler(MissingServletRequestParameterException e) { |
||||
|
return _innerHandler(Result.ILLEGAL_ARGUMENT, e, false); |
||||
|
} |
||||
|
|
||||
|
@ResponseBody |
||||
|
@ExceptionHandler({MultipartException.class, MethodArgumentTypeMismatchException.class}) |
||||
|
public Result errorHandler(MultipartException e) { |
||||
|
return _innerHandler(Result.NOT_SUPPORT, e, false); |
||||
|
} |
||||
|
|
||||
|
@ResponseBody |
||||
|
@ExceptionHandler |
||||
|
public Result errorHandler(Exception e) { |
||||
|
return _innerHandler(Result.ERROR, e, true); |
||||
|
} |
||||
|
|
||||
|
@SneakyThrows |
||||
|
private Result _innerHandler(Result result, Exception e, boolean needExceptionTrace) { |
||||
|
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); |
||||
|
if (requestAttributes != null) { |
||||
|
if (requestAttributes.getResponse() != null) { |
||||
|
byte[] response = JSON.toJSONString(new Result(result.getCode(), result.equals(Result.ERROR) ? "系统异常!" : e.getMessage())).getBytes(StandardCharsets.UTF_8); |
||||
|
requestAttributes.getResponse().setContentType("text/json; charset=utf-8"); |
||||
|
requestAttributes.getResponse().setStatus(result.getCode()); |
||||
|
requestAttributes.getResponse().setContentLength(response.length); |
||||
|
requestAttributes.getResponse().getOutputStream().write(response); |
||||
|
} |
||||
|
HttpServletRequest request = requestAttributes.getRequest(); |
||||
|
if (!needExceptionTrace) { |
||||
|
log.error(String.format("[GlobalExceptionHandler:%s] %s %s exception=%s", request.getMethod(), request.getServletPath(), JSON.toJSONString(request.getParameterMap()), e.getMessage())); |
||||
|
} else { |
||||
|
log.error(String.format("[GlobalExceptionHandler:%s] %s %s exception=%s", request.getMethod(), request.getServletPath(), JSON.toJSONString(request.getParameterMap()), e.getMessage()), e); |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,95 @@ |
|||||
|
package com.mathvision.diet.aspect; |
||||
|
|
||||
|
import com.alibaba.fastjson2.JSON; |
||||
|
import com.mathvision.diet.constant.Constant; |
||||
|
import com.mathvision.diet.domain.Result; |
||||
|
import com.mathvision.diet.domain.Session; |
||||
|
import com.mathvision.diet.domain.UserDO; |
||||
|
import com.mathvision.diet.domian.AuthType; |
||||
|
import com.mathvision.diet.entity.RoleItem; |
||||
|
import com.mathvision.diet.exception.DietException; |
||||
|
import com.mathvision.diet.service.DemoEnvLimitService; |
||||
|
import com.mathvision.diet.service.EnumService; |
||||
|
import com.mathvision.diet.utils.JWTUtils; |
||||
|
import lombok.NonNull; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.util.Assert; |
||||
|
import org.springframework.web.bind.annotation.ControllerAdvice; |
||||
|
import org.springframework.web.servlet.HandlerInterceptor; |
||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||
|
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
import java.util.List; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ControllerAdvice |
||||
|
public class GlobalRequestAspect implements HandlerInterceptor, WebMvcConfigurer { |
||||
|
|
||||
|
@Resource |
||||
|
EnumService enumService; |
||||
|
|
||||
|
@Resource |
||||
|
DemoEnvLimitService demoEnvLimitService; |
||||
|
|
||||
|
@Override |
||||
|
public void addInterceptors(InterceptorRegistry registry) { |
||||
|
registry.addInterceptor(this) |
||||
|
.addPathPatterns("/api/**") |
||||
|
.excludePathPatterns("/api/icon/*.*") |
||||
|
.excludePathPatterns("/api/login") |
||||
|
.excludePathPatterns("/api/logout"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws IOException { |
||||
|
if (handler instanceof ResourceHttpRequestHandler) { |
||||
|
response.setStatus(Result.NOT_SUPPORT.getCode()); |
||||
|
response.setCharacterEncoding("UTF-8"); |
||||
|
response.setContentType("text/json; charset=utf-8"); |
||||
|
response.getOutputStream().write(JSON.toJSONString(Result.NOT_SUPPORT).getBytes(StandardCharsets.UTF_8)); |
||||
|
return false; |
||||
|
} |
||||
|
demoEnvLimitService.checkRateLimit(); |
||||
|
return verifySession(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) { |
||||
|
Session.clear(); |
||||
|
} |
||||
|
|
||||
|
private boolean verifySession(HttpServletRequest request, HttpServletResponse response) { |
||||
|
String token = request.getHeader(Constant.TOKEN_HEADER_KEY); |
||||
|
if (StringUtils.isBlank(token)) { |
||||
|
throw new DietException(Result.NOT_LOGIN); |
||||
|
} |
||||
|
UserDO userDO = JWTUtils.verify(token); |
||||
|
if (userDO == null) { |
||||
|
throw new DietException(Result.NOT_LOGIN); |
||||
|
} else { |
||||
|
userDO.setRoleItems(enumService.getRoleItems(userDO.getRoleItems().stream().map(RoleItem::getId).collect(Collectors.toList()))); |
||||
|
Session.set(userDO); |
||||
|
} |
||||
|
if (!hasRole(userDO.isAdmin() ? AuthType.SERVER : AuthType.CLIENT, userDO.getRoleItems(), request.getRequestURI().toLowerCase(), request.getMethod().toLowerCase())) { |
||||
|
throw new DietException(Result.NOT_PRIVILEGED); |
||||
|
} |
||||
|
response.setHeader(Constant.TOKEN_HEADER_KEY, JWTUtils.getToken(userDO)); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private boolean hasRole(AuthType authType, List<RoleItem> roleItems, String url, String method) { |
||||
|
return !enumService.getAuthItems(authType).contains(url) || roleItems.parallelStream() |
||||
|
.map(item -> item.getItemValue().split(":", 2)) |
||||
|
.anyMatch(item -> item.length == 2 && item[0].contains(method) && url.matches("^/api/(" + item[1] + ")$")); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,53 @@ |
|||||
|
package com.mathvision.diet.aspect; |
||||
|
|
||||
|
import com.alibaba.fastjson.serializer.SerializerFeature; |
||||
|
import com.alibaba.fastjson.support.config.FastJsonConfig; |
||||
|
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; |
||||
|
import com.mathvision.diet.constant.Constant; |
||||
|
import com.mathvision.diet.domain.Result; |
||||
|
import com.mathvision.diet.domain.ResultCode; |
||||
|
import lombok.NonNull; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.context.annotation.Bean; |
||||
|
import org.springframework.context.annotation.Configuration; |
||||
|
import org.springframework.core.MethodParameter; |
||||
|
import org.springframework.http.MediaType; |
||||
|
import org.springframework.http.converter.HttpMessageConverter; |
||||
|
import org.springframework.http.server.ServerHttpRequest; |
||||
|
import org.springframework.http.server.ServerHttpResponse; |
||||
|
import org.springframework.web.bind.annotation.ControllerAdvice; |
||||
|
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; |
||||
|
|
||||
|
import java.nio.charset.StandardCharsets; |
||||
|
|
||||
|
@Slf4j |
||||
|
@Configuration |
||||
|
@ControllerAdvice |
||||
|
public class GlobalResponseAspect implements ResponseBodyAdvice<Object> { |
||||
|
|
||||
|
@Override |
||||
|
public boolean supports(@NonNull MethodParameter methodParameter, @NonNull Class clazz) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
@Bean |
||||
|
FastJsonHttpMessageConverter fastJsonHttpMessageConverters() { |
||||
|
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); |
||||
|
FastJsonConfig jsonConfig = new FastJsonConfig(); |
||||
|
jsonConfig.setCharset(StandardCharsets.UTF_8); |
||||
|
jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); |
||||
|
jsonConfig.setSerializerFeatures(SerializerFeature.BrowserCompatible); |
||||
|
converter.setFastJsonConfig(jsonConfig); |
||||
|
converter.setDefaultCharset(StandardCharsets.UTF_8); |
||||
|
converter.setSupportedMediaTypes(Constant.SUPPORTED_MEDIA_TYPES); |
||||
|
return converter; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Object beforeBodyWrite(Object result, @NonNull MethodParameter methodParameter, @NonNull MediaType mediaType, @NonNull Class<? extends HttpMessageConverter<?>> clazz, @NonNull ServerHttpRequest serverHttpRequest, @NonNull ServerHttpResponse serverHttpResponse) { |
||||
|
if (result instanceof Result) { |
||||
|
return result; |
||||
|
} |
||||
|
return new Result(ResultCode.success, result); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
package com.mathvision.diet.constant; |
||||
|
|
||||
|
import com.google.common.collect.Lists; |
||||
|
import org.springframework.http.MediaType; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class Constant { |
||||
|
public static final int TOKEN_EXPIRE_SECOND = 7200; |
||||
|
public static final String TOKEN_HEADER_KEY = "Authorization"; |
||||
|
|
||||
|
public static final List<MediaType> SUPPORTED_MEDIA_TYPES = Lists.newArrayList( |
||||
|
MediaType.APPLICATION_JSON, |
||||
|
MediaType.APPLICATION_ATOM_XML, |
||||
|
MediaType.APPLICATION_FORM_URLENCODED, |
||||
|
MediaType.APPLICATION_OCTET_STREAM, |
||||
|
MediaType.APPLICATION_PDF, |
||||
|
MediaType.APPLICATION_RSS_XML, |
||||
|
MediaType.APPLICATION_XHTML_XML, |
||||
|
MediaType.APPLICATION_XML, |
||||
|
MediaType.IMAGE_GIF, |
||||
|
MediaType.IMAGE_JPEG, |
||||
|
MediaType.IMAGE_PNG, |
||||
|
MediaType.TEXT_EVENT_STREAM, |
||||
|
MediaType.TEXT_HTML, |
||||
|
MediaType.TEXT_MARKDOWN, |
||||
|
MediaType.TEXT_PLAIN, |
||||
|
MediaType.TEXT_XML |
||||
|
); |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
package com.mathvision.diet.controller; |
||||
|
|
||||
|
import com.mathvision.diet.domain.Result; |
||||
|
import com.mathvision.diet.domain.UserDO; |
||||
|
import com.mathvision.diet.domian.ClientType; |
||||
|
import com.mathvision.diet.entity.Vender; |
||||
|
import com.mathvision.diet.exception.DietException; |
||||
|
import com.mathvision.diet.service.UserService; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.springframework.stereotype.Controller; |
||||
|
import org.springframework.util.Assert; |
||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||
|
import org.springframework.web.bind.annotation.RequestMethod; |
||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||
|
import org.springframework.web.bind.annotation.ResponseBody; |
||||
|
|
||||
|
import javax.annotation.Resource; |
||||
|
import java.time.Instant; |
||||
|
|
||||
|
@RequestMapping("/api") |
||||
|
@Controller |
||||
|
public class AuthController extends BaseController { |
||||
|
@Resource |
||||
|
private UserService userService; |
||||
|
|
||||
|
@ResponseBody |
||||
|
@RequestMapping("login") |
||||
|
public UserDO login(@RequestParam String uid, @RequestParam String pwd, @RequestParam(required = false, defaultValue = "false") Boolean admin, @RequestParam(required = false, defaultValue = "WEB") String clientType, @RequestParam(required = false, defaultValue = "1.0") String clientVersion) { |
||||
|
if(StringUtils.isBlank(uid) || StringUtils.isBlank(pwd)) { |
||||
|
throw new DietException(Result.ILLEGAL_ARGUMENT); |
||||
|
} |
||||
|
UserDO userDO = userService.login(uid, pwd, ClientType.valueOf(clientType), clientVersion); |
||||
|
if (userDO == null || userDO.isAdmin() && !admin || !userDO.isAdmin() && admin) { |
||||
|
throw new DietException(Result.INVALID_USER_PASS); |
||||
|
} |
||||
|
Vender vender = userDO.getVender(); |
||||
|
if (vender != null && (!vender.getStatus() || Instant.now().isAfter(vender.getExpire()))) { |
||||
|
throw new DietException(Result.EXPIRED); |
||||
|
} |
||||
|
setSession(userDO); |
||||
|
return userDO; |
||||
|
} |
||||
|
|
||||
|
@ResponseBody |
||||
|
@RequestMapping(value = "password", method = RequestMethod.POST) |
||||
|
public void password(@RequestParam String oldPassword, @RequestParam String password) { |
||||
|
Assert.isTrue(userService.checkUser(getUid(), oldPassword), "[参数错误]用户名密码错误!"); |
||||
|
userService.changeUser(getUid(), null, password, null, getVender(), getUid()); |
||||
|
delSession(); |
||||
|
} |
||||
|
|
||||
|
@ResponseBody |
||||
|
@RequestMapping("logout") |
||||
|
public void logout() { |
||||
|
userService.logout(getUid()); |
||||
|
delSession(); |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue