菜谱排餐
This commit is contained in:
1 parent
245efd3936
commit
91a2facb83
24 files changed
+1294
No files matched your search
+23
@@ -0,0 +1,23 @@
|
||||
package com.bsd.pjcloud.canteen.dto.mealplan;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
@Schema(description = "排餐计划明细项")
|
||||
public class CanteenMealPlanItemDTO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private LocalDate planDate;
|
||||
|
||||
private Integer mealSegment;
|
||||
|
||||
private Long recipeId;
|
||||
|
||||
private String recipeName;
|
||||
|
||||
private Integer sortOrder;
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package com.bsd.pjcloud.canteen.dto.mealplan;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "保存排餐计划")
|
||||
public class CanteenMealPlanSaveDTO {
|
||||
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "请选择商户")
|
||||
private String merchantId;
|
||||
|
||||
@NotBlank(message = "请输入计划名称")
|
||||
private String planName;
|
||||
|
||||
@NotNull(message = "请选择开始日期")
|
||||
private LocalDate startDate;
|
||||
|
||||
@NotNull(message = "请填写排餐天数")
|
||||
private Integer dayCount;
|
||||
|
||||
@NotEmpty(message = "请勾选餐次")
|
||||
private List<Integer> mealSegments;
|
||||
|
||||
private List<Long> selectedMaterialIds;
|
||||
|
||||
private Integer matchMode;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String remark;
|
||||
|
||||
private List<CanteenMealPlanItemDTO> items;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.bsd.pjcloud.canteen.dto.menurecipe;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "按选用食材匹配菜谱")
|
||||
public class CanteenMenuRecipeMatchDTO {
|
||||
|
||||
@Schema(description = "已选食材ID")
|
||||
private List<Long> materialIds;
|
||||
|
||||
@Schema(description = "可选:限定商户")
|
||||
private String merchantId;
|
||||
}
|
||||
+8
@@ -113,4 +113,12 @@ public class CanteenErpMaterialEntity extends Model<CanteenErpMaterialEntity> {
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<CanteenMaterialNutritionTagDTO> nutritionTags;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "筛选:营养元素名称")
|
||||
private String nutritionName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "筛选:营养功效")
|
||||
private String nutritionEffect;
|
||||
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.bsd.pjcloud.canteen.entity;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||
import com.bsd.pjcloud.common.core.util.TenantTable;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@TenantTable
|
||||
@TableName(value = "canteen_meal_plan", autoResultMap = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "排餐计划")
|
||||
public class CanteenMealPlanEntity extends Model<CanteenMealPlanEntity> {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
private Long tenantId;
|
||||
|
||||
private Long deptId;
|
||||
|
||||
private String merchantId;
|
||||
|
||||
private String planName;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private Integer dayCount;
|
||||
|
||||
@TableField(value = "meal_segments_json", typeHandler = JacksonTypeHandler.class)
|
||||
private List<Integer> mealSegments;
|
||||
|
||||
@TableField(value = "selected_material_ids_json", typeHandler = JacksonTypeHandler.class)
|
||||
private List<Long> selectedMaterialIds;
|
||||
|
||||
private Integer matchMode;
|
||||
|
||||
@Schema(description = "0草稿 1已定稿")
|
||||
private Integer status;
|
||||
|
||||
private String remark;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@TableLogic
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String delFlag;
|
||||
|
||||
@ExcelIgnore
|
||||
@TableField(exist = false)
|
||||
private String merchantName;
|
||||
|
||||
@ExcelIgnore
|
||||
@TableField(exist = false)
|
||||
private List<CanteenMealPlanItemEntity> itemList;
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.bsd.pjcloud.canteen.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("canteen_meal_plan_item")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "排餐计划明细")
|
||||
public class CanteenMealPlanItemEntity extends Model<CanteenMealPlanItemEntity> {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
private Long planId;
|
||||
|
||||
private LocalDate planDate;
|
||||
|
||||
@Schema(description = "1早2午3晚4夜")
|
||||
private Integer mealSegment;
|
||||
|
||||
private Long recipeId;
|
||||
|
||||
private String recipeName;
|
||||
|
||||
private Integer sortOrder;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package com.bsd.pjcloud.canteen.entity;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import com.bsd.pjcloud.common.core.util.TenantTable;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@TenantTable
|
||||
@TableName("canteen_menu_recipe")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "排菜菜谱")
|
||||
public class CanteenMenuRecipeEntity extends Model<CanteenMenuRecipeEntity> {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
private Long tenantId;
|
||||
|
||||
@Schema(description = "所属部门")
|
||||
private Long deptId;
|
||||
|
||||
@Schema(description = "关联商户")
|
||||
private String merchantId;
|
||||
|
||||
@Schema(description = "菜名")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "图片")
|
||||
private String picUrl;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "可选关联线上商品")
|
||||
private Long onlineSpuId;
|
||||
|
||||
@Schema(description = "0正常 1停用")
|
||||
private Integer status;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private String updateBy;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@TableLogic
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String delFlag;
|
||||
|
||||
@ExcelIgnore
|
||||
@TableField(exist = false)
|
||||
private List<CanteenMenuRecipeMaterialEntity> materialList;
|
||||
|
||||
@ExcelIgnore
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "食材摘要(列表展示)")
|
||||
private String materialSummary;
|
||||
|
||||
@ExcelIgnore
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "关联线上商品名称")
|
||||
private String onlineSpuName;
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.bsd.pjcloud.canteen.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("canteen_menu_recipe_material")
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "排菜菜谱-食材明细")
|
||||
public class CanteenMenuRecipeMaterialEntity extends Model<CanteenMenuRecipeMaterialEntity> {
|
||||
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
private Long recipeId;
|
||||
|
||||
private Long materialId;
|
||||
|
||||
@Schema(description = "参考用量")
|
||||
private BigDecimal quantity;
|
||||
|
||||
private Integer sortOrder;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String materialName;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String unit;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.bsd.pjcloud.canteen.vo.mealplan;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CanteenMealPlanExportRow {
|
||||
|
||||
@ExcelProperty("日期")
|
||||
private String planDate;
|
||||
|
||||
@ExcelProperty("餐次")
|
||||
private String mealSegmentName;
|
||||
|
||||
@ExcelProperty("菜名")
|
||||
private String recipeName;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.bsd.pjcloud.canteen.vo.mealplan;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Schema(description = "排餐选用食材摘要")
|
||||
public class CanteenMealPlanMaterialBriefVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String unit;
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.bsd.pjcloud.canteen.vo.mealplan;
|
||||
|
||||
import com.bsd.pjcloud.canteen.dto.mealplan.CanteenMealPlanItemDTO;
|
||||
import com.bsd.pjcloud.canteen.vo.menurecipe.CanteenMenuRecipeVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "排餐计划详情")
|
||||
public class CanteenMealPlanVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String merchantId;
|
||||
|
||||
private String merchantName;
|
||||
|
||||
private String planName;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private Integer dayCount;
|
||||
|
||||
private List<Integer> mealSegments;
|
||||
|
||||
private List<Long> selectedMaterialIds;
|
||||
|
||||
private Integer matchMode;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private String remark;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private List<LocalDate> planDates;
|
||||
|
||||
private List<CanteenMealPlanItemDTO> items;
|
||||
|
||||
private List<CanteenMealPlanMaterialBriefVO> selectedMaterials;
|
||||
|
||||
private List<CanteenMenuRecipeVO> matchedRecipes;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.bsd.pjcloud.canteen.vo.menurecipe;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Schema(description = "排菜菜谱食材明细")
|
||||
public class CanteenMenuRecipeMaterialVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long materialId;
|
||||
|
||||
private String materialName;
|
||||
|
||||
private String unit;
|
||||
|
||||
private BigDecimal quantity;
|
||||
|
||||
private Integer sortOrder;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.bsd.pjcloud.canteen.vo.menurecipe;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Schema(description = "排菜菜谱详情")
|
||||
public class CanteenMenuRecipeVO {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Long deptId;
|
||||
|
||||
private String merchantId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String picUrl;
|
||||
|
||||
private String remark;
|
||||
|
||||
private Long onlineSpuId;
|
||||
|
||||
private String onlineSpuName;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private String materialSummary;
|
||||
|
||||
private List<CanteenMenuRecipeMaterialVO> materialList;
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
package com.bsd.pjcloud.canteen.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.bsd.pjcloud.canteen.dto.mealplan.CanteenMealPlanSaveDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMealPlanEntity;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenMealPlanService;
|
||||
import com.bsd.pjcloud.canteen.vo.mealplan.CanteenMealPlanExportRow;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springdoc.core.annotations.ParameterObject;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/canteenMealPlan")
|
||||
@Tag(name = "一键排餐")
|
||||
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||
public class CanteenMealPlanController {
|
||||
|
||||
private final CanteenMealPlanService canteenMealPlanService;
|
||||
|
||||
@Operation(summary = "分页查询")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_view')")
|
||||
public R<Page<CanteenMealPlanEntity>> page(@ParameterObject Page<CanteenMealPlanEntity> page,
|
||||
@ParameterObject CanteenMealPlanEntity query) {
|
||||
var wrapper = Wrappers.<CanteenMealPlanEntity>lambdaQuery()
|
||||
.like(StrUtil.isNotBlank(query.getPlanName()), CanteenMealPlanEntity::getPlanName, query.getPlanName())
|
||||
.eq(StrUtil.isNotBlank(query.getMerchantId()), CanteenMealPlanEntity::getMerchantId,
|
||||
query.getMerchantId())
|
||||
.eq(query.getStatus() != null, CanteenMealPlanEntity::getStatus, query.getStatus())
|
||||
.orderByDesc(CanteenMealPlanEntity::getCreateTime);
|
||||
return R.ok(canteenMealPlanService.pageScope(page, wrapper));
|
||||
}
|
||||
|
||||
@Operation(summary = "详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_view')")
|
||||
public R getById(@PathVariable Long id) {
|
||||
return R.ok(canteenMealPlanService.getDetail(id));
|
||||
}
|
||||
|
||||
@SysLog("新增排餐计划")
|
||||
@Operation(summary = "新增")
|
||||
@PostMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_add')")
|
||||
public R<Long> save(@Valid @RequestBody CanteenMealPlanSaveDTO dto) {
|
||||
return R.ok(canteenMealPlanService.savePlan(dto));
|
||||
}
|
||||
|
||||
@SysLog("修改排餐计划")
|
||||
@Operation(summary = "修改")
|
||||
@PutMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_edit')")
|
||||
public R update(@Valid @RequestBody CanteenMealPlanSaveDTO dto) {
|
||||
return R.ok(canteenMealPlanService.updatePlan(dto));
|
||||
}
|
||||
|
||||
@SysLog("删除排餐计划")
|
||||
@Operation(summary = "删除")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_del')")
|
||||
public R remove(@RequestBody Long[] ids) {
|
||||
return R.ok(canteenMealPlanService.removePlans(ids));
|
||||
}
|
||||
|
||||
@ResponseExcel(name = "排餐明细")
|
||||
@Operation(summary = "导出明细(日期+餐次+菜名)")
|
||||
@GetMapping("/export/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_export')")
|
||||
public List<CanteenMealPlanExportRow> exportDetail(@PathVariable Long id) {
|
||||
return canteenMealPlanService.exportRows(id);
|
||||
}
|
||||
|
||||
@Operation(summary = "导出餐表(横轴日期、纵轴餐次)")
|
||||
@GetMapping("/export-grid/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMealPlan_export')")
|
||||
public void exportGrid(@PathVariable Long id, HttpServletResponse response) {
|
||||
canteenMealPlanService.exportGridExcel(id, response);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package com.bsd.pjcloud.canteen.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.bsd.pjcloud.canteen.dto.menurecipe.CanteenMenuRecipeMatchDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeEntity;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenMenuRecipeService;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springdoc.core.annotations.ParameterObject;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/canteenMenuRecipe")
|
||||
@Tag(name = "排菜菜谱")
|
||||
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
|
||||
public class CanteenMenuRecipeController {
|
||||
|
||||
private final CanteenMenuRecipeService canteenMenuRecipeService;
|
||||
|
||||
@Operation(summary = "分页查询")
|
||||
@GetMapping("/page")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMenuRecipe_view')")
|
||||
public R<Page<CanteenMenuRecipeEntity>> page(@ParameterObject Page<CanteenMenuRecipeEntity> page,
|
||||
@ParameterObject CanteenMenuRecipeEntity query) {
|
||||
var wrapper = Wrappers.<CanteenMenuRecipeEntity>lambdaQuery()
|
||||
.like(StrUtil.isNotBlank(query.getName()), CanteenMenuRecipeEntity::getName, query.getName())
|
||||
.eq(StrUtil.isNotBlank(query.getMerchantId()), CanteenMenuRecipeEntity::getMerchantId,
|
||||
query.getMerchantId())
|
||||
.eq(query.getStatus() != null, CanteenMenuRecipeEntity::getStatus, query.getStatus())
|
||||
.orderByDesc(CanteenMenuRecipeEntity::getCreateTime);
|
||||
return R.ok(canteenMenuRecipeService.pageScope(page, wrapper));
|
||||
}
|
||||
|
||||
@Operation(summary = "详情")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMenuRecipe_view')")
|
||||
public R getById(@PathVariable Long id) {
|
||||
return R.ok(canteenMenuRecipeService.getDetail(id));
|
||||
}
|
||||
|
||||
@SysLog("新增排菜菜谱")
|
||||
@Operation(summary = "新增")
|
||||
@PostMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMenuRecipe_add')")
|
||||
public R save(@RequestBody CanteenMenuRecipeEntity entity) {
|
||||
entity.setDeptId(SecurityUtils.getUser().getDeptId());
|
||||
return R.ok(canteenMenuRecipeService.saveDeep(entity));
|
||||
}
|
||||
|
||||
@SysLog("修改排菜菜谱")
|
||||
@Operation(summary = "修改")
|
||||
@PutMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMenuRecipe_edit')")
|
||||
public R update(@RequestBody CanteenMenuRecipeEntity entity) {
|
||||
return R.ok(canteenMenuRecipeService.updateDeep(entity));
|
||||
}
|
||||
|
||||
@SysLog("删除排菜菜谱")
|
||||
@Operation(summary = "删除")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMenuRecipe_del')")
|
||||
public R remove(@RequestBody Long[] ids) {
|
||||
return R.ok(canteenMenuRecipeService.removeDeep(ids));
|
||||
}
|
||||
|
||||
@Operation(summary = "按选用食材匹配可做菜谱", description = "所选食材须覆盖菜谱全部食材")
|
||||
@PostMapping("/match-by-materials")
|
||||
@PreAuthorize("@pms.hasPermission('canteen_canteenMenuRecipe_view')")
|
||||
public R<List<?>> matchByMaterials(@RequestBody CanteenMenuRecipeMatchDTO dto) {
|
||||
return R.ok(canteenMenuRecipeService.matchByMaterials(dto));
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.bsd.pjcloud.canteen.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMealPlanItemEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CanteenMealPlanItemMapper extends BaseMapper<CanteenMealPlanItemEntity> {
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.bsd.pjcloud.canteen.mapper;
|
||||
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMealPlanEntity;
|
||||
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CanteenMealPlanMapper extends PjcloudBaseMapper<CanteenMealPlanEntity> {
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.bsd.pjcloud.canteen.mapper;
|
||||
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeEntity;
|
||||
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CanteenMenuRecipeMapper extends PjcloudBaseMapper<CanteenMenuRecipeEntity> {
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.bsd.pjcloud.canteen.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeMaterialEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CanteenMenuRecipeMaterialMapper extends BaseMapper<CanteenMenuRecipeMaterialEntity> {
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.bsd.pjcloud.canteen.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.bsd.pjcloud.canteen.dto.mealplan.CanteenMealPlanSaveDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMealPlanEntity;
|
||||
import com.bsd.pjcloud.canteen.vo.mealplan.CanteenMealPlanExportRow;
|
||||
import com.bsd.pjcloud.canteen.vo.mealplan.CanteenMealPlanVO;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CanteenMealPlanService extends IService<CanteenMealPlanEntity> {
|
||||
|
||||
Page<CanteenMealPlanEntity> pageScope(Page<CanteenMealPlanEntity> page, LambdaQueryWrapper<CanteenMealPlanEntity> wrapper);
|
||||
|
||||
Long savePlan(CanteenMealPlanSaveDTO dto);
|
||||
|
||||
Boolean updatePlan(CanteenMealPlanSaveDTO dto);
|
||||
|
||||
Boolean removePlans(Long[] ids);
|
||||
|
||||
CanteenMealPlanVO getDetail(Long id);
|
||||
|
||||
List<CanteenMealPlanExportRow> exportRows(Long id);
|
||||
|
||||
void exportGridExcel(Long id, HttpServletResponse response);
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.bsd.pjcloud.canteen.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.bsd.pjcloud.canteen.dto.menurecipe.CanteenMenuRecipeMatchDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeEntity;
|
||||
import com.bsd.pjcloud.canteen.vo.menurecipe.CanteenMenuRecipeVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface CanteenMenuRecipeService extends IService<CanteenMenuRecipeEntity> {
|
||||
|
||||
Page<CanteenMenuRecipeEntity> pageScope(Page<CanteenMenuRecipeEntity> page, LambdaQueryWrapper<CanteenMenuRecipeEntity> wrapper);
|
||||
|
||||
Boolean saveDeep(CanteenMenuRecipeEntity entity);
|
||||
|
||||
Boolean updateDeep(CanteenMenuRecipeEntity entity);
|
||||
|
||||
Boolean removeDeep(Long[] ids);
|
||||
|
||||
CanteenMenuRecipeVO getDetail(Long id);
|
||||
|
||||
List<CanteenMenuRecipeVO> matchByMaterials(CanteenMenuRecipeMatchDTO dto);
|
||||
}
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
package com.bsd.pjcloud.canteen.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.canteen.dto.mealplan.CanteenMealPlanItemDTO;
|
||||
import com.bsd.pjcloud.canteen.dto.mealplan.CanteenMealPlanSaveDTO;
|
||||
import com.bsd.pjcloud.canteen.dto.menurecipe.CanteenMenuRecipeMatchDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenErpMaterialEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMealPlanEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMealPlanItemEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeEntity;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenErpMaterialMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenMealPlanItemMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenMealPlanMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenMenuRecipeMapper;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenMealPlanService;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenMenuRecipeService;
|
||||
import com.bsd.pjcloud.canteen.vo.mealplan.CanteenMealPlanExportRow;
|
||||
import com.bsd.pjcloud.canteen.vo.mealplan.CanteenMealPlanMaterialBriefVO;
|
||||
import com.bsd.pjcloud.canteen.vo.mealplan.CanteenMealPlanVO;
|
||||
import com.bsd.pjcloud.canteen.vo.menurecipe.CanteenMenuRecipeVO;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.data.datascope.DataScope;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
|
||||
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CanteenMealPlanServiceImpl extends ServiceImpl<CanteenMealPlanMapper, CanteenMealPlanEntity>
|
||||
implements CanteenMealPlanService {
|
||||
|
||||
private static final Map<Integer, String> SEGMENT_NAMES = Map.of(
|
||||
1, "早餐",
|
||||
2, "午餐",
|
||||
3, "晚餐",
|
||||
4, "夜宵");
|
||||
|
||||
private static final String[] WEEKDAY_LABELS = { "日", "一", "二", "三", "四", "五", "六" };
|
||||
|
||||
private final CanteenMealPlanItemMapper itemMapper;
|
||||
private final CanteenErpMaterialMapper erpMaterialMapper;
|
||||
private final CanteenMenuRecipeService menuRecipeService;
|
||||
private final CanteenMenuRecipeMapper menuRecipeMapper;
|
||||
private final RemoteMchService remoteMchService;
|
||||
|
||||
@Override
|
||||
public Page<CanteenMealPlanEntity> pageScope(Page<CanteenMealPlanEntity> page,
|
||||
LambdaQueryWrapper<CanteenMealPlanEntity> wrapper) {
|
||||
Page<CanteenMealPlanEntity> result = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
fillMerchantNames(result.getRecords());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long savePlan(CanteenMealPlanSaveDTO dto) {
|
||||
CanteenMealPlanEntity entity = toEntity(dto);
|
||||
entity.setDeptId(SecurityUtils.getUser().getDeptId());
|
||||
if (entity.getMatchMode() == null) {
|
||||
entity.setMatchMode(1);
|
||||
}
|
||||
if (entity.getStatus() == null) {
|
||||
entity.setStatus(0);
|
||||
}
|
||||
baseMapper.insert(entity);
|
||||
saveItems(entity.getId(), dto.getItems());
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updatePlan(CanteenMealPlanSaveDTO dto) {
|
||||
CanteenMealPlanEntity entity = toEntity(dto);
|
||||
baseMapper.updateById(entity);
|
||||
itemMapper.delete(Wrappers.<CanteenMealPlanItemEntity>lambdaQuery()
|
||||
.eq(CanteenMealPlanItemEntity::getPlanId, dto.getId()));
|
||||
saveItems(dto.getId(), dto.getItems());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean removePlans(Long[] ids) {
|
||||
if (ids == null || ids.length == 0) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
baseMapper.deleteBatchIds(CollUtil.toList(ids));
|
||||
itemMapper.delete(Wrappers.<CanteenMealPlanItemEntity>lambdaQuery()
|
||||
.in(CanteenMealPlanItemEntity::getPlanId, CollUtil.toList(ids)));
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CanteenMealPlanVO getDetail(Long id) {
|
||||
CanteenMealPlanEntity entity = baseMapper.selectById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
CanteenMealPlanVO vo = BeanUtils.toBean(entity, CanteenMealPlanVO.class);
|
||||
vo.setMerchantName(resolveMerchantName(entity.getMerchantId()));
|
||||
vo.setPlanDates(buildPlanDates(entity.getStartDate(), entity.getDayCount()));
|
||||
List<CanteenMealPlanItemEntity> items = itemMapper.selectList(
|
||||
Wrappers.<CanteenMealPlanItemEntity>lambdaQuery()
|
||||
.eq(CanteenMealPlanItemEntity::getPlanId, id)
|
||||
.orderByAsc(CanteenMealPlanItemEntity::getPlanDate)
|
||||
.orderByAsc(CanteenMealPlanItemEntity::getMealSegment)
|
||||
.orderByAsc(CanteenMealPlanItemEntity::getSortOrder));
|
||||
vo.setItems(BeanUtils.toBean(items, CanteenMealPlanItemDTO.class));
|
||||
vo.setSelectedMaterials(loadMaterialBriefs(entity.getSelectedMaterialIds()));
|
||||
if (CollUtil.isNotEmpty(entity.getSelectedMaterialIds())) {
|
||||
CanteenMenuRecipeMatchDTO matchDTO = new CanteenMenuRecipeMatchDTO();
|
||||
matchDTO.setMaterialIds(entity.getSelectedMaterialIds());
|
||||
matchDTO.setMerchantId(entity.getMerchantId());
|
||||
vo.setMatchedRecipes(menuRecipeService.matchByMaterials(matchDTO));
|
||||
} else {
|
||||
vo.setMatchedRecipes(Collections.emptyList());
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CanteenMealPlanExportRow> exportRows(Long id) {
|
||||
CanteenMealPlanVO detail = getDetail(id);
|
||||
if (detail == null || CollUtil.isEmpty(detail.getItems())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<CanteenMealPlanExportRow> rows = new ArrayList<>();
|
||||
for (CanteenMealPlanItemDTO item : detail.getItems()) {
|
||||
CanteenMealPlanExportRow row = new CanteenMealPlanExportRow();
|
||||
row.setPlanDate(item.getPlanDate() != null ? item.getPlanDate().toString() : "");
|
||||
row.setMealSegmentName(SEGMENT_NAMES.getOrDefault(item.getMealSegment(), String.valueOf(item.getMealSegment())));
|
||||
row.setRecipeName(item.getRecipeName());
|
||||
rows.add(row);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportGridExcel(Long id, HttpServletResponse response) {
|
||||
CanteenMealPlanVO detail = getDetail(id);
|
||||
if (detail == null) {
|
||||
throw new IllegalArgumentException("排餐计划不存在");
|
||||
}
|
||||
List<LocalDate> dates = detail.getPlanDates();
|
||||
List<Integer> segments = detail.getMealSegments() != null ? detail.getMealSegments() : Collections.emptyList();
|
||||
Map<String, List<String>> cellMap = new LinkedHashMap<>();
|
||||
if (CollUtil.isNotEmpty(detail.getItems())) {
|
||||
for (CanteenMealPlanItemDTO item : detail.getItems()) {
|
||||
if (item.getPlanDate() == null || item.getMealSegment() == null) {
|
||||
continue;
|
||||
}
|
||||
String name = item.getRecipeName() != null ? item.getRecipeName().trim() : "";
|
||||
if (name.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String key = buildCellKey(item.getPlanDate(), item.getMealSegment());
|
||||
cellMap.computeIfAbsent(key, k -> new ArrayList<>()).add(name);
|
||||
}
|
||||
}
|
||||
List<List<String>> rows = new ArrayList<>();
|
||||
List<String> header = new ArrayList<>();
|
||||
header.add("餐次");
|
||||
for (LocalDate d : dates) {
|
||||
header.add(formatDateHeader(d));
|
||||
}
|
||||
rows.add(header);
|
||||
for (Integer seg : segments) {
|
||||
List<String> line = new ArrayList<>();
|
||||
line.add(SEGMENT_NAMES.getOrDefault(seg, String.valueOf(seg)));
|
||||
for (LocalDate d : dates) {
|
||||
line.add(formatCellRecipes(cellMap.get(buildCellKey(d, seg))));
|
||||
}
|
||||
rows.add(line);
|
||||
}
|
||||
try {
|
||||
String fileName = URLEncoder.encode(
|
||||
(detail.getPlanName() != null ? detail.getPlanName() : "排餐计划") + "-餐表.xlsx",
|
||||
StandardCharsets.UTF_8).replace("+", "%20");
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);
|
||||
EasyExcel.write(response.getOutputStream()).sheet("排餐餐表").doWrite(rows);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("导出失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private CanteenMealPlanEntity toEntity(CanteenMealPlanSaveDTO dto) {
|
||||
CanteenMealPlanEntity entity = BeanUtils.toBean(dto, CanteenMealPlanEntity.class);
|
||||
if (entity.getDayCount() == null || entity.getDayCount() < 1) {
|
||||
entity.setDayCount(1);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
private void saveItems(Long planId, List<CanteenMealPlanItemDTO> items) {
|
||||
if (CollUtil.isEmpty(items)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, String> recipeNameMap = loadRecipeNames(items);
|
||||
int sort = 0;
|
||||
for (CanteenMealPlanItemDTO dto : items) {
|
||||
if (dto.getPlanDate() == null || dto.getMealSegment() == null || dto.getRecipeId() == null) {
|
||||
continue;
|
||||
}
|
||||
CanteenMealPlanItemEntity item = new CanteenMealPlanItemEntity();
|
||||
item.setPlanId(planId);
|
||||
item.setPlanDate(dto.getPlanDate());
|
||||
item.setMealSegment(dto.getMealSegment());
|
||||
item.setRecipeId(dto.getRecipeId());
|
||||
String name = dto.getRecipeName();
|
||||
if (name == null || name.isBlank()) {
|
||||
name = recipeNameMap.get(dto.getRecipeId());
|
||||
}
|
||||
item.setRecipeName(name);
|
||||
item.setSortOrder(dto.getSortOrder() != null ? dto.getSortOrder() : sort++);
|
||||
itemMapper.insert(item);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, String> loadRecipeNames(List<CanteenMealPlanItemDTO> items) {
|
||||
Set<Long> ids = items.stream().map(CanteenMealPlanItemDTO::getRecipeId).filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
if (ids.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return menuRecipeMapper.selectBatchIds(ids).stream()
|
||||
.collect(Collectors.toMap(CanteenMenuRecipeEntity::getId, CanteenMenuRecipeEntity::getName, (a, b) -> a));
|
||||
}
|
||||
|
||||
private List<CanteenMealPlanMaterialBriefVO> loadMaterialBriefs(List<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return erpMaterialMapper.selectBatchIds(ids).stream().map(m -> {
|
||||
CanteenMealPlanMaterialBriefVO vo = new CanteenMealPlanMaterialBriefVO();
|
||||
vo.setId(m.getId());
|
||||
vo.setName(m.getName());
|
||||
vo.setUnit(m.getUnit());
|
||||
return vo;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
private List<LocalDate> buildPlanDates(LocalDate startDate, Integer dayCount) {
|
||||
if (startDate == null || dayCount == null || dayCount < 1) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<LocalDate> list = new ArrayList<>();
|
||||
for (int i = 0; i < dayCount; i++) {
|
||||
list.add(startDate.plusDays(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void fillMerchantNames(List<CanteenMealPlanEntity> records) {
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
Map<String, String> nameMap = loadMerchantNameMap(records.stream()
|
||||
.map(CanteenMealPlanEntity::getMerchantId)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toList()));
|
||||
for (CanteenMealPlanEntity record : records) {
|
||||
if (StrUtil.isBlank(record.getMerchantId())) {
|
||||
continue;
|
||||
}
|
||||
record.setMerchantName(nameMap.getOrDefault(record.getMerchantId().trim(), record.getMerchantId()));
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveMerchantName(String merchantId) {
|
||||
if (StrUtil.isBlank(merchantId)) {
|
||||
return null;
|
||||
}
|
||||
return loadMerchantNameMap(Collections.singletonList(merchantId))
|
||||
.getOrDefault(merchantId.trim(), merchantId);
|
||||
}
|
||||
|
||||
private Map<String, String> loadMerchantNameMap(List<String> merchantIds) {
|
||||
if (CollUtil.isEmpty(merchantIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
List<Long> ids = merchantIds.stream()
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(String::trim)
|
||||
.distinct()
|
||||
.map(id -> {
|
||||
try {
|
||||
return Long.parseLong(id);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (ids.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
R<List<MchManageVo>> resp = remoteMchService.getByIds(ids);
|
||||
if (resp == null || !resp.isOk() || CollUtil.isEmpty(resp.getData())) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return resp.getData().stream()
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(m -> String.valueOf(m.getId()), MchManageVo::getName, (a, b) -> a));
|
||||
}
|
||||
|
||||
private String buildCellKey(LocalDate planDate, Integer mealSegment) {
|
||||
return planDate + "_" + mealSegment;
|
||||
}
|
||||
|
||||
private String formatDateHeader(LocalDate date) {
|
||||
int weekday = date.getDayOfWeek().getValue() % 7;
|
||||
return date.format(DateTimeFormatter.ofPattern("M月d日")) + " 周" + WEEKDAY_LABELS[weekday];
|
||||
}
|
||||
|
||||
private String formatCellRecipes(List<String> recipeNames) {
|
||||
if (CollUtil.isEmpty(recipeNames)) {
|
||||
return "";
|
||||
}
|
||||
return IntStream.range(0, recipeNames.size())
|
||||
.mapToObj(i -> (i + 1) + ". " + recipeNames.get(i))
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
package com.bsd.pjcloud.canteen.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.canteen.dto.menurecipe.CanteenMenuRecipeMatchDTO;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenErpMaterialEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenMenuRecipeMaterialEntity;
|
||||
import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenErpMaterialMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenMenuRecipeMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenMenuRecipeMaterialMapper;
|
||||
import com.bsd.pjcloud.canteen.mapper.CanteenOnlineSpuMapper;
|
||||
import com.bsd.pjcloud.canteen.service.CanteenMenuRecipeService;
|
||||
import com.bsd.pjcloud.canteen.vo.menurecipe.CanteenMenuRecipeMaterialVO;
|
||||
import com.bsd.pjcloud.canteen.vo.menurecipe.CanteenMenuRecipeVO;
|
||||
import com.bsd.pjcloud.common.core.util.BeanUtils;
|
||||
import com.bsd.pjcloud.common.data.datascope.DataScope;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CanteenMenuRecipeServiceImpl extends ServiceImpl<CanteenMenuRecipeMapper, CanteenMenuRecipeEntity>
|
||||
implements CanteenMenuRecipeService {
|
||||
|
||||
private final CanteenMenuRecipeMaterialMapper materialMapper;
|
||||
private final CanteenErpMaterialMapper erpMaterialMapper;
|
||||
private final CanteenOnlineSpuMapper onlineSpuMapper;
|
||||
|
||||
@Override
|
||||
public Page<CanteenMenuRecipeEntity> pageScope(Page<CanteenMenuRecipeEntity> page,
|
||||
LambdaQueryWrapper<CanteenMenuRecipeEntity> wrapper) {
|
||||
Page<CanteenMenuRecipeEntity> pageData = baseMapper.selectPageByScope(page, wrapper, DataScope.of());
|
||||
fillListExtras(pageData.getRecords());
|
||||
return pageData;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean saveDeep(CanteenMenuRecipeEntity entity) {
|
||||
if (entity.getStatus() == null) {
|
||||
entity.setStatus(0);
|
||||
}
|
||||
baseMapper.insert(entity);
|
||||
saveMaterials(entity.getId(), entity.getMaterialList());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean updateDeep(CanteenMenuRecipeEntity entity) {
|
||||
baseMapper.updateById(entity);
|
||||
materialMapper.delete(Wrappers.<CanteenMenuRecipeMaterialEntity>lambdaQuery()
|
||||
.eq(CanteenMenuRecipeMaterialEntity::getRecipeId, entity.getId()));
|
||||
saveMaterials(entity.getId(), entity.getMaterialList());
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean removeDeep(Long[] ids) {
|
||||
if (ids == null || ids.length == 0) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
baseMapper.deleteBatchIds(CollUtil.toList(ids));
|
||||
materialMapper.delete(Wrappers.<CanteenMenuRecipeMaterialEntity>lambdaQuery()
|
||||
.in(CanteenMenuRecipeMaterialEntity::getRecipeId, CollUtil.toList(ids)));
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CanteenMenuRecipeVO getDetail(Long id) {
|
||||
CanteenMenuRecipeEntity entity = baseMapper.selectById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
CanteenMenuRecipeVO vo = BeanUtils.toBean(entity, CanteenMenuRecipeVO.class);
|
||||
vo.setMaterialList(loadMaterialVos(id));
|
||||
vo.setMaterialSummary(buildMaterialSummary(vo.getMaterialList()));
|
||||
if (entity.getOnlineSpuId() != null) {
|
||||
CanteenOnlineSpuEntity spu = onlineSpuMapper.selectById(entity.getOnlineSpuId());
|
||||
if (spu != null) {
|
||||
vo.setOnlineSpuName(spu.getName());
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CanteenMenuRecipeVO> matchByMaterials(CanteenMenuRecipeMatchDTO dto) {
|
||||
if (dto == null || CollUtil.isEmpty(dto.getMaterialIds())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Long> selected = new HashSet<>(dto.getMaterialIds());
|
||||
LambdaQueryWrapper<CanteenMenuRecipeEntity> wrapper = Wrappers.<CanteenMenuRecipeEntity>lambdaQuery()
|
||||
.eq(CanteenMenuRecipeEntity::getStatus, 0);
|
||||
if (StringUtils.isNotBlank(dto.getMerchantId())) {
|
||||
wrapper.and(w -> w.eq(CanteenMenuRecipeEntity::getMerchantId, dto.getMerchantId())
|
||||
.or().isNull(CanteenMenuRecipeEntity::getMerchantId)
|
||||
.or().eq(CanteenMenuRecipeEntity::getMerchantId, ""));
|
||||
}
|
||||
List<CanteenMenuRecipeEntity> recipes = baseMapper.selectListByScope(wrapper, DataScope.of());
|
||||
if (CollUtil.isEmpty(recipes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Long> recipeIds = recipes.stream().map(CanteenMenuRecipeEntity::getId).toList();
|
||||
List<CanteenMenuRecipeMaterialEntity> allLines = materialMapper.selectList(
|
||||
Wrappers.<CanteenMenuRecipeMaterialEntity>lambdaQuery()
|
||||
.in(CanteenMenuRecipeMaterialEntity::getRecipeId, recipeIds)
|
||||
.orderByAsc(CanteenMenuRecipeMaterialEntity::getSortOrder));
|
||||
Map<Long, List<Long>> recipeMaterialMap = allLines.stream()
|
||||
.collect(Collectors.groupingBy(CanteenMenuRecipeMaterialEntity::getRecipeId,
|
||||
Collectors.mapping(CanteenMenuRecipeMaterialEntity::getMaterialId, Collectors.toList())));
|
||||
|
||||
List<CanteenMenuRecipeVO> matched = new ArrayList<>();
|
||||
for (CanteenMenuRecipeEntity recipe : recipes) {
|
||||
List<Long> needIds = recipeMaterialMap.getOrDefault(recipe.getId(), Collections.emptyList());
|
||||
if (CollUtil.isEmpty(needIds)) {
|
||||
continue;
|
||||
}
|
||||
if (selected.containsAll(needIds)) {
|
||||
matched.add(getDetail(recipe.getId()));
|
||||
}
|
||||
}
|
||||
return matched;
|
||||
}
|
||||
|
||||
private void saveMaterials(Long recipeId, List<CanteenMenuRecipeMaterialEntity> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
int sort = 0;
|
||||
for (CanteenMenuRecipeMaterialEntity line : list) {
|
||||
if (line.getMaterialId() == null) {
|
||||
continue;
|
||||
}
|
||||
line.setId(null);
|
||||
line.setRecipeId(recipeId);
|
||||
if (line.getSortOrder() == null) {
|
||||
line.setSortOrder(sort++);
|
||||
}
|
||||
materialMapper.insert(line);
|
||||
}
|
||||
}
|
||||
|
||||
private List<CanteenMenuRecipeMaterialVO> loadMaterialVos(Long recipeId) {
|
||||
List<CanteenMenuRecipeMaterialEntity> lines = materialMapper.selectList(
|
||||
Wrappers.<CanteenMenuRecipeMaterialEntity>lambdaQuery()
|
||||
.eq(CanteenMenuRecipeMaterialEntity::getRecipeId, recipeId)
|
||||
.orderByAsc(CanteenMenuRecipeMaterialEntity::getSortOrder));
|
||||
if (CollUtil.isEmpty(lines)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<CanteenMenuRecipeMaterialVO> vos = BeanUtils.toBean(lines, CanteenMenuRecipeMaterialVO.class);
|
||||
for (CanteenMenuRecipeMaterialVO vo : vos) {
|
||||
CanteenErpMaterialEntity material = erpMaterialMapper.selectById(vo.getMaterialId());
|
||||
if (material != null) {
|
||||
vo.setMaterialName(material.getName());
|
||||
vo.setUnit(material.getUnit());
|
||||
}
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
private void fillListExtras(List<CanteenMenuRecipeEntity> records) {
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
return;
|
||||
}
|
||||
List<Long> recipeIds = records.stream().map(CanteenMenuRecipeEntity::getId).toList();
|
||||
List<CanteenMenuRecipeMaterialEntity> allLines = materialMapper.selectList(
|
||||
Wrappers.<CanteenMenuRecipeMaterialEntity>lambdaQuery()
|
||||
.in(CanteenMenuRecipeMaterialEntity::getRecipeId, recipeIds)
|
||||
.orderByAsc(CanteenMenuRecipeMaterialEntity::getSortOrder));
|
||||
Set<Long> materialIds = allLines.stream().map(CanteenMenuRecipeMaterialEntity::getMaterialId)
|
||||
.filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
Map<Long, CanteenErpMaterialEntity> materialMap = materialIds.isEmpty() ? Collections.emptyMap()
|
||||
: erpMaterialMapper.selectBatchIds(materialIds).stream()
|
||||
.collect(Collectors.toMap(CanteenErpMaterialEntity::getId, m -> m, (a, b) -> a));
|
||||
|
||||
Map<Long, List<CanteenMenuRecipeMaterialEntity>> grouped = allLines.stream()
|
||||
.collect(Collectors.groupingBy(CanteenMenuRecipeMaterialEntity::getRecipeId));
|
||||
|
||||
Set<Long> spuIds = records.stream().map(CanteenMenuRecipeEntity::getOnlineSpuId).filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Map<Long, String> spuNameMap = spuIds.isEmpty() ? Collections.emptyMap()
|
||||
: onlineSpuMapper.selectBatchIds(spuIds).stream()
|
||||
.collect(Collectors.toMap(CanteenOnlineSpuEntity::getId, CanteenOnlineSpuEntity::getName, (a, b) -> a));
|
||||
|
||||
for (CanteenMenuRecipeEntity record : records) {
|
||||
List<CanteenMenuRecipeMaterialEntity> lines = grouped.getOrDefault(record.getId(), Collections.emptyList());
|
||||
String summary = lines.stream().map(line -> {
|
||||
CanteenErpMaterialEntity m = materialMap.get(line.getMaterialId());
|
||||
return m != null ? m.getName() : String.valueOf(line.getMaterialId());
|
||||
}).collect(Collectors.joining("、"));
|
||||
record.setMaterialSummary(summary);
|
||||
if (record.getOnlineSpuId() != null) {
|
||||
record.setOnlineSpuName(spuNameMap.get(record.getOnlineSpuId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String buildMaterialSummary(List<CanteenMenuRecipeMaterialVO> list) {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return "";
|
||||
}
|
||||
return list.stream()
|
||||
.map(vo -> vo.getMaterialName() != null ? vo.getMaterialName() : String.valueOf(vo.getMaterialId()))
|
||||
.collect(Collectors.joining("、"));
|
||||
}
|
||||
}
|
||||
+6
@@ -61,6 +61,12 @@
|
||||
<if test="canteenErpMaterial.materialType != null">
|
||||
and m.material_type = #{canteenErpMaterial.materialType}
|
||||
</if>
|
||||
<if test="canteenErpMaterial.nutritionName != null and canteenErpMaterial.nutritionName != ''">
|
||||
and m.nutrition_tags like concat('%"name":"%', #{canteenErpMaterial.nutritionName}, '%')
|
||||
</if>
|
||||
<if test="canteenErpMaterial.nutritionEffect != null and canteenErpMaterial.nutritionEffect != ''">
|
||||
and m.nutrition_tags like concat('%"effect":"%', #{canteenErpMaterial.nutritionEffect}, '%')
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in new issue
Block a user