Browse Source

低糖标签BUG修复 202601

master
fangyang2021 4 weeks ago
commit
0130a26503
  1. 37
      .gitignore
  2. 58
      diet-core/pom.xml
  3. 17
      diet-core/src/main/java/com/mathvision/diet/domain/ComponentAnalysisDO.java
  4. 20
      diet-core/src/main/java/com/mathvision/diet/domain/DishLabelDO.java
  5. 33
      diet-core/src/main/java/com/mathvision/diet/domain/UserDO.java
  6. 48
      diet-core/src/main/java/com/mathvision/diet/excel/BigDecimalStringConverter.java
  7. 69
      diet-core/src/main/java/com/mathvision/diet/excel/IngredientModel.java
  8. 31
      diet-core/src/main/java/com/mathvision/diet/excel/ResultModel.java
  9. 70
      diet-core/src/main/java/com/mathvision/diet/service/DemoEnvLimitService.java
  10. 297
      diet-core/src/main/java/com/mathvision/diet/service/DishService.java
  11. 153
      diet-core/src/main/java/com/mathvision/diet/service/EnumService.java
  12. 244
      diet-core/src/main/java/com/mathvision/diet/service/IngredientService.java
  13. 273
      diet-core/src/main/java/com/mathvision/diet/service/MenuDishService.java
  14. 93
      diet-core/src/main/java/com/mathvision/diet/service/MenuReleaseService.java
  15. 447
      diet-core/src/main/java/com/mathvision/diet/service/MenuReportService.java
  16. 105
      diet-core/src/main/java/com/mathvision/diet/service/MenuReviewService.java
  17. 138
      diet-core/src/main/java/com/mathvision/diet/service/MenuService.java
  18. 104
      diet-core/src/main/java/com/mathvision/diet/service/NutritionService.java
  19. 69
      diet-core/src/main/java/com/mathvision/diet/service/SugarService.java
  20. 274
      diet-core/src/main/java/com/mathvision/diet/service/UserService.java
  21. 143
      diet-core/src/main/java/com/mathvision/diet/service/VenderService.java
  22. 25
      diet-core/src/main/java/com/mathvision/diet/word/ServerTableData.java
  23. 80
      diet-core/src/main/java/com/mathvision/diet/word/ServerTablePolicy.java
  24. 48
      diet-dao/pom.xml
  25. 19
      diet-dao/src/main/java/com/mathvision/diet/convert/AuthTypeConvert.java
  26. 22
      diet-dao/src/main/java/com/mathvision/diet/convert/DishItemConvert.java
  27. 19
      diet-dao/src/main/java/com/mathvision/diet/convert/GenderTypeConvert.java
  28. 22
      diet-dao/src/main/java/com/mathvision/diet/convert/IngredientConvert.java
  29. 19
      diet-dao/src/main/java/com/mathvision/diet/convert/MarkTypeConvert.java
  30. 23
      diet-dao/src/main/java/com/mathvision/diet/convert/MenuDishConvert.java
  31. 19
      diet-dao/src/main/java/com/mathvision/diet/convert/MenuStatusConvert.java
  32. 19
      diet-dao/src/main/java/com/mathvision/diet/convert/RoleTypeConvert.java
  33. 23
      diet-dao/src/main/java/com/mathvision/diet/convert/RuleItemConvert.java
  34. 19
      diet-dao/src/main/java/com/mathvision/diet/convert/VenderTypeConvert.java
  35. 26
      diet-dao/src/main/java/com/mathvision/diet/domian/AuthType.java
  36. 5
      diet-dao/src/main/java/com/mathvision/diet/domian/ClientType.java
  37. 17
      diet-dao/src/main/java/com/mathvision/diet/domian/DishItemDTO.java
  38. 25
      diet-dao/src/main/java/com/mathvision/diet/domian/GenderType.java
  39. 32
      diet-dao/src/main/java/com/mathvision/diet/domian/IngredientDTO.java
  40. 25
      diet-dao/src/main/java/com/mathvision/diet/domian/MarkType.java
  41. 25
      diet-dao/src/main/java/com/mathvision/diet/domian/MealType.java
  42. 25
      diet-dao/src/main/java/com/mathvision/diet/domian/MeasurementType.java
  43. 30
      diet-dao/src/main/java/com/mathvision/diet/domian/MenuCountDTO.java
  44. 28
      diet-dao/src/main/java/com/mathvision/diet/domian/MenuDishItemDTO.java
  45. 39
      diet-dao/src/main/java/com/mathvision/diet/domian/MenuStatus.java
  46. 5
      diet-dao/src/main/java/com/mathvision/diet/domian/MessageType.java
  47. 62
      diet-dao/src/main/java/com/mathvision/diet/domian/NutritionSortEnum.java
  48. 25
      diet-dao/src/main/java/com/mathvision/diet/domian/RoleType.java
  49. 58
      diet-dao/src/main/java/com/mathvision/diet/domian/RuleItemDTO.java
  50. 25
      diet-dao/src/main/java/com/mathvision/diet/domian/VenderType.java
  51. 76
      diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java
  52. 41
      diet-dao/src/main/java/com/mathvision/diet/entity/FoodCategory.java
  53. 41
      diet-dao/src/main/java/com/mathvision/diet/entity/FoodMark.java
  54. 48
      diet-dao/src/main/java/com/mathvision/diet/entity/FoodNutrient.java
  55. 42
      diet-dao/src/main/java/com/mathvision/diet/entity/FoodPoly.java
  56. 64
      diet-dao/src/main/java/com/mathvision/diet/entity/Ingredient.java
  57. 50
      diet-dao/src/main/java/com/mathvision/diet/entity/IngredientMark.java
  58. 95
      diet-dao/src/main/java/com/mathvision/diet/entity/Menu.java
  59. 43
      diet-dao/src/main/java/com/mathvision/diet/entity/MenuApprove.java
  60. 72
      diet-dao/src/main/java/com/mathvision/diet/entity/MenuDish.java
  61. 73
      diet-dao/src/main/java/com/mathvision/diet/entity/Nutrition.java
  62. 57
      diet-dao/src/main/java/com/mathvision/diet/entity/Role.java
  63. 52
      diet-dao/src/main/java/com/mathvision/diet/entity/RoleItem.java
  64. 70
      diet-dao/src/main/java/com/mathvision/diet/entity/Sugar.java
  65. 64
      diet-dao/src/main/java/com/mathvision/diet/entity/User.java
  66. 41
      diet-dao/src/main/java/com/mathvision/diet/entity/UserLog.java
  67. 47
      diet-dao/src/main/java/com/mathvision/diet/entity/UserMessage.java
  68. 44
      diet-dao/src/main/java/com/mathvision/diet/entity/UserRole.java
  69. 50
      diet-dao/src/main/java/com/mathvision/diet/entity/UserSession.java
  70. 89
      diet-dao/src/main/java/com/mathvision/diet/entity/Vender.java
  71. 51
      diet-dao/src/main/java/com/mathvision/diet/entity/VenderConfig.java
  72. 34
      diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java
  73. 8
      diet-dao/src/main/java/com/mathvision/diet/repository/FoodCategoryRepository.java
  74. 8
      diet-dao/src/main/java/com/mathvision/diet/repository/FoodMarkRepository.java
  75. 8
      diet-dao/src/main/java/com/mathvision/diet/repository/FoodNutrientRepository.java
  76. 8
      diet-dao/src/main/java/com/mathvision/diet/repository/FoodPolyRepository.java
  77. 16
      diet-dao/src/main/java/com/mathvision/diet/repository/IngredientDTORepository.java
  78. 23
      diet-dao/src/main/java/com/mathvision/diet/repository/IngredientMarkRepository.java
  79. 42
      diet-dao/src/main/java/com/mathvision/diet/repository/IngredientRepository.java
  80. 15
      diet-dao/src/main/java/com/mathvision/diet/repository/MenuApproveRepository.java
  81. 37
      diet-dao/src/main/java/com/mathvision/diet/repository/MenuDishRepository.java
  82. 59
      diet-dao/src/main/java/com/mathvision/diet/repository/MenuRepository.java
  83. 16
      diet-dao/src/main/java/com/mathvision/diet/repository/NutritionRepository.java
  84. 8
      diet-dao/src/main/java/com/mathvision/diet/repository/RoleItemRepository.java
  85. 35
      diet-dao/src/main/java/com/mathvision/diet/repository/RoleRepository.java
  86. 11
      diet-dao/src/main/java/com/mathvision/diet/repository/SugarRepository.java
  87. 23
      diet-dao/src/main/java/com/mathvision/diet/repository/UserLogRepository.java
  88. 16
      diet-dao/src/main/java/com/mathvision/diet/repository/UserMessageRepository.java
  89. 30
      diet-dao/src/main/java/com/mathvision/diet/repository/UserRepository.java
  90. 26
      diet-dao/src/main/java/com/mathvision/diet/repository/UserRoleRepository.java
  91. 16
      diet-dao/src/main/java/com/mathvision/diet/repository/UserSessionRepository.java
  92. 19
      diet-dao/src/main/java/com/mathvision/diet/repository/VenderConfigRepository.java
  93. 33
      diet-dao/src/main/java/com/mathvision/diet/repository/VenderRepository.java
  94. 65
      diet-web/pom.xml
  95. 13
      diet-web/src/main/java/com/mathvision/diet/Application.java
  96. 79
      diet-web/src/main/java/com/mathvision/diet/aspect/GlobalExceptionHandler.java
  97. 95
      diet-web/src/main/java/com/mathvision/diet/aspect/GlobalRequestAspect.java
  98. 53
      diet-web/src/main/java/com/mathvision/diet/aspect/GlobalResponseAspect.java
  99. 30
      diet-web/src/main/java/com/mathvision/diet/constant/Constant.java
  100. 58
      diet-web/src/main/java/com/mathvision/diet/controller/AuthController.java

37
.gitignore

@ -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!/

58
diet-core/pom.xml

@ -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>

17
diet-core/src/main/java/com/mathvision/diet/domain/ComponentAnalysisDO.java

@ -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;
}

20
diet-core/src/main/java/com/mathvision/diet/domain/DishLabelDO.java

@ -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;
}

33
diet-core/src/main/java/com/mathvision/diet/domain/UserDO.java

@ -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;
}
}

48
diet-core/src/main/java/com/mathvision/diet/excel/BigDecimalStringConverter.java

@ -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);
}
}

69
diet-core/src/main/java/com/mathvision/diet/excel/IngredientModel.java

@ -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;
}

31
diet-core/src/main/java/com/mathvision/diet/excel/ResultModel.java

@ -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;
}

70
diet-core/src/main/java/com/mathvision/diet/service/DemoEnvLimitService.java

@ -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;
}
}

297
diet-core/src/main/java/com/mathvision/diet/service/DishService.java

@ -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);
}
}

153
diet-core/src/main/java/com/mathvision/diet/service/EnumService.java

@ -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);
}
}

244
diet-core/src/main/java/com/mathvision/diet/service/IngredientService.java

@ -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);
}
}

273
diet-core/src/main/java/com/mathvision/diet/service/MenuDishService.java

@ -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 "";
}
}
}

93
diet-core/src/main/java/com/mathvision/diet/service/MenuReleaseService.java

@ -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);
}
};
}
}

447
diet-core/src/main/java/com/mathvision/diet/service/MenuReportService.java

@ -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);
}
}

105
diet-core/src/main/java/com/mathvision/diet/service/MenuReviewService.java

@ -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);
// }
// };
// }
}

138
diet-core/src/main/java/com/mathvision/diet/service/MenuService.java

@ -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);
}
};
}
}

104
diet-core/src/main/java/com/mathvision/diet/service/NutritionService.java

@ -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);
}
}

69
diet-core/src/main/java/com/mathvision/diet/service/SugarService.java

@ -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);
}
};
}
}

274
diet-core/src/main/java/com/mathvision/diet/service/UserService.java

@ -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);
}
}

143
diet-core/src/main/java/com/mathvision/diet/service/VenderService.java

@ -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);
}
}

25
diet-core/src/main/java/com/mathvision/diet/word/ServerTableData.java

@ -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;
}

80
diet-core/src/main/java/com/mathvision/diet/word/ServerTablePolicy.java

@ -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);
}
}
}

48
diet-dao/pom.xml

@ -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>

19
diet-dao/src/main/java/com/mathvision/diet/convert/AuthTypeConvert.java

@ -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);
}
}

22
diet-dao/src/main/java/com/mathvision/diet/convert/DishItemConvert.java

@ -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>>(){});
}
}

19
diet-dao/src/main/java/com/mathvision/diet/convert/GenderTypeConvert.java

@ -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);
}
}

22
diet-dao/src/main/java/com/mathvision/diet/convert/IngredientConvert.java

@ -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>>>>(){});
}
}

19
diet-dao/src/main/java/com/mathvision/diet/convert/MarkTypeConvert.java

@ -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);
}
}

23
diet-dao/src/main/java/com/mathvision/diet/convert/MenuDishConvert.java

@ -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>>>(){});
}
}

19
diet-dao/src/main/java/com/mathvision/diet/convert/MenuStatusConvert.java

@ -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);
}
}

19
diet-dao/src/main/java/com/mathvision/diet/convert/RoleTypeConvert.java

@ -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);
}
}

23
diet-dao/src/main/java/com/mathvision/diet/convert/RuleItemConvert.java

@ -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);
}
}

19
diet-dao/src/main/java/com/mathvision/diet/convert/VenderTypeConvert.java

@ -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);
}
}

26
diet-dao/src/main/java/com/mathvision/diet/domian/AuthType.java

@ -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);
}
}

5
diet-dao/src/main/java/com/mathvision/diet/domian/ClientType.java

@ -0,0 +1,5 @@
package com.mathvision.diet.domian;
public enum ClientType {
IOS, Android, WEB
}

17
diet-dao/src/main/java/com/mathvision/diet/domian/DishItemDTO.java

@ -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;
}

25
diet-dao/src/main/java/com/mathvision/diet/domian/GenderType.java

@ -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);
}
}

32
diet-dao/src/main/java/com/mathvision/diet/domian/IngredientDTO.java

@ -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;
}

25
diet-dao/src/main/java/com/mathvision/diet/domian/MarkType.java

@ -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);
}
}

25
diet-dao/src/main/java/com/mathvision/diet/domian/MealType.java

@ -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);
}
}

25
diet-dao/src/main/java/com/mathvision/diet/domian/MeasurementType.java

@ -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);
}
}

30
diet-dao/src/main/java/com/mathvision/diet/domian/MenuCountDTO.java

@ -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;
}

28
diet-dao/src/main/java/com/mathvision/diet/domian/MenuDishItemDTO.java

@ -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;
}

39
diet-dao/src/main/java/com/mathvision/diet/domian/MenuStatus.java

@ -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);
}
}

5
diet-dao/src/main/java/com/mathvision/diet/domian/MessageType.java

@ -0,0 +1,5 @@
package com.mathvision.diet.domian;
public enum MessageType {
CODE, NOTIFY, MESSAGE
}

62
diet-dao/src/main/java/com/mathvision/diet/domian/NutritionSortEnum.java

@ -0,0 +1,62 @@
package com.mathvision.diet.domian;
import java.util.*;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
/**
* @author fy
* @description: 营养素排序枚举
*/
public enum NutritionSortEnum {
ENERGY("能量/kcal"),
PROTEIN("蛋白质/g"),
FAT("脂肪/g"),
CARBOHYDRATE("碳水化合物/g"),
CALCIUM("钙/mg"),
IRON("铁/mg"),
ZINC("锌/mg"),
VITAMIN_A("维生素A/μgRAE"),
VITAMIN_B1("维生素B1/mg"),
VITAMIN_B2("维生素B2/mg"),
VITAMIN_C("维生素C/mg"),
DIETARY_FIBER("膳食纤维/g"),
SODIUM("钠/mg");
private final String label;
private static final Map<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);
}
}

25
diet-dao/src/main/java/com/mathvision/diet/domian/RoleType.java

@ -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);
}
}

58
diet-dao/src/main/java/com/mathvision/diet/domian/RuleItemDTO.java

@ -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);
}
}

25
diet-dao/src/main/java/com/mathvision/diet/domian/VenderType.java

@ -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);
}
}

76
diet-dao/src/main/java/com/mathvision/diet/entity/Dish.java

@ -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;
}

41
diet-dao/src/main/java/com/mathvision/diet/entity/FoodCategory.java

@ -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;
}

41
diet-dao/src/main/java/com/mathvision/diet/entity/FoodMark.java

@ -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;
}

48
diet-dao/src/main/java/com/mathvision/diet/entity/FoodNutrient.java

@ -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;
}

42
diet-dao/src/main/java/com/mathvision/diet/entity/FoodPoly.java

@ -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;
}

64
diet-dao/src/main/java/com/mathvision/diet/entity/Ingredient.java

@ -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;
}

50
diet-dao/src/main/java/com/mathvision/diet/entity/IngredientMark.java

@ -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;
}

95
diet-dao/src/main/java/com/mathvision/diet/entity/Menu.java

@ -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;
}

43
diet-dao/src/main/java/com/mathvision/diet/entity/MenuApprove.java

@ -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;
}

72
diet-dao/src/main/java/com/mathvision/diet/entity/MenuDish.java

@ -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;
}

73
diet-dao/src/main/java/com/mathvision/diet/entity/Nutrition.java

@ -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;
}

57
diet-dao/src/main/java/com/mathvision/diet/entity/Role.java

@ -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;
}

52
diet-dao/src/main/java/com/mathvision/diet/entity/RoleItem.java

@ -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;
}

70
diet-dao/src/main/java/com/mathvision/diet/entity/Sugar.java

@ -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;
}

64
diet-dao/src/main/java/com/mathvision/diet/entity/User.java

@ -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;
}

41
diet-dao/src/main/java/com/mathvision/diet/entity/UserLog.java

@ -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;
}

47
diet-dao/src/main/java/com/mathvision/diet/entity/UserMessage.java

@ -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;
}

44
diet-dao/src/main/java/com/mathvision/diet/entity/UserRole.java

@ -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;
}

50
diet-dao/src/main/java/com/mathvision/diet/entity/UserSession.java

@ -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;
}

89
diet-dao/src/main/java/com/mathvision/diet/entity/Vender.java

@ -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;
}

51
diet-dao/src/main/java/com/mathvision/diet/entity/VenderConfig.java

@ -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;
}

34
diet-dao/src/main/java/com/mathvision/diet/repository/DishRepository.java

@ -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);
}

8
diet-dao/src/main/java/com/mathvision/diet/repository/FoodCategoryRepository.java

@ -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> {
}

8
diet-dao/src/main/java/com/mathvision/diet/repository/FoodMarkRepository.java

@ -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> {
}

8
diet-dao/src/main/java/com/mathvision/diet/repository/FoodNutrientRepository.java

@ -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> {
}

8
diet-dao/src/main/java/com/mathvision/diet/repository/FoodPolyRepository.java

@ -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> {
}

16
diet-dao/src/main/java/com/mathvision/diet/repository/IngredientDTORepository.java

@ -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);
}

23
diet-dao/src/main/java/com/mathvision/diet/repository/IngredientMarkRepository.java

@ -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);
}

42
diet-dao/src/main/java/com/mathvision/diet/repository/IngredientRepository.java

@ -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);
}

15
diet-dao/src/main/java/com/mathvision/diet/repository/MenuApproveRepository.java

@ -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();
}

37
diet-dao/src/main/java/com/mathvision/diet/repository/MenuDishRepository.java

@ -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);
}

59
diet-dao/src/main/java/com/mathvision/diet/repository/MenuRepository.java

@ -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();
}

16
diet-dao/src/main/java/com/mathvision/diet/repository/NutritionRepository.java

@ -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);
}

8
diet-dao/src/main/java/com/mathvision/diet/repository/RoleItemRepository.java

@ -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> {
}

35
diet-dao/src/main/java/com/mathvision/diet/repository/RoleRepository.java

@ -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);
}

11
diet-dao/src/main/java/com/mathvision/diet/repository/SugarRepository.java

@ -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);
}

23
diet-dao/src/main/java/com/mathvision/diet/repository/UserLogRepository.java

@ -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();
}

16
diet-dao/src/main/java/com/mathvision/diet/repository/UserMessageRepository.java

@ -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();
}

30
diet-dao/src/main/java/com/mathvision/diet/repository/UserRepository.java

@ -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);
}

26
diet-dao/src/main/java/com/mathvision/diet/repository/UserRoleRepository.java

@ -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);
}

16
diet-dao/src/main/java/com/mathvision/diet/repository/UserSessionRepository.java

@ -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();
}

19
diet-dao/src/main/java/com/mathvision/diet/repository/VenderConfigRepository.java

@ -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);
}

33
diet-dao/src/main/java/com/mathvision/diet/repository/VenderRepository.java

@ -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);
}

65
diet-web/pom.xml

@ -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>

13
diet-web/src/main/java/com/mathvision/diet/Application.java

@ -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);
}
}

79
diet-web/src/main/java/com/mathvision/diet/aspect/GlobalExceptionHandler.java

@ -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;
}
}

95
diet-web/src/main/java/com/mathvision/diet/aspect/GlobalRequestAspect.java

@ -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] + ")$"));
}
}

53
diet-web/src/main/java/com/mathvision/diet/aspect/GlobalResponseAspect.java

@ -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);
}
}

30
diet-web/src/main/java/com/mathvision/diet/constant/Constant.java

@ -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
);
}

58
diet-web/src/main/java/com/mathvision/diet/controller/AuthController.java

@ -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…
Cancel
Save