浏览代码

菜品多功能查询 及 删除逻辑

lutong 1 月之前
父节点
当前提交
e314fb86a0

+ 1 - 1
alien-dining/src/main/java/shop/alien/dining/controller/DiningController.java

@@ -29,7 +29,7 @@ public class DiningController {
 
     private final DiningService diningService;
 
-    @ApiOperation(value = "查询餐桌是否处于就餐中", notes = "免登录可调用,用于前端判断是否跳过选择用餐人数;根据 status=就餐中 且 diner_count 有值 判定为就餐中")
+    @ApiOperation(value = "查询餐桌是否处于就餐中", notes = "免登录可调用,用于前端判断是否跳过选择用餐人数。就餐中(status=1)、加餐(status=3) 均视为就餐状态,且 diner_count 有值 时 inDining=true")
     @GetMapping("/table-dining-status")
     public R<TableDiningStatusVO> getTableDiningStatus(
             @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {

+ 35 - 0
alien-dining/src/main/java/shop/alien/dining/controller/StoreInfoController.java

@@ -9,6 +9,7 @@ import shop.alien.entity.store.StoreCuisine;
 import shop.alien.entity.store.StoreCuisineCategory;
 import shop.alien.entity.store.StoreTable;
 import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
+import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
 import shop.alien.dining.service.StoreInfoService;
 
 import java.util.List;
@@ -63,6 +64,40 @@ public class StoreInfoController {
         }
     }
 
+    @ApiOperation(value = "根据门店ID查询菜品种类及各类别下菜品", notes = "一次返回所有菜品种类及每个分类下的菜品列表")
+    @GetMapping("/categories-with-cuisines")
+    public R<List<CategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
+            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
+        log.info("StoreInfoController.getCategoriesWithCuisinesByStoreId?storeId={}", storeId);
+        try {
+            if (storeId == null) {
+                return R.fail("门店ID不能为空");
+            }
+            List<CategoryWithCuisinesVO> list = storeInfoService.getCategoriesWithCuisinesByStoreId(storeId);
+            return R.data(list);
+        } catch (Exception e) {
+            log.error("查询菜品种类及菜品失败: {}", e.getMessage(), e);
+            return R.fail("查询菜品种类及菜品失败: " + e.getMessage());
+        }
+    }
+
+    @ApiOperation(value = "删除菜品种类", notes = "仅删除绑定关系和菜品种类(逻辑删除);价目表中的菜品记录不删除、其它字段不变,仅从 category_ids 中移除该分类ID")
+    @DeleteMapping("/category/{categoryId}")
+    public R<Boolean> deleteCategory(
+            @ApiParam(value = "菜品种类ID", required = true) @PathVariable Integer categoryId) {
+        log.info("StoreInfoController.deleteCategory?categoryId={}", categoryId);
+        try {
+            if (categoryId == null) {
+                return R.fail("菜品种类ID不能为空");
+            }
+            boolean result = storeInfoService.deleteCategory(categoryId);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("删除菜品种类失败: {}", e.getMessage(), e);
+            return R.fail("删除菜品种类失败: " + e.getMessage());
+        }
+    }
+
     @ApiOperation(value = "根据菜品种类ID查询菜品信息列表", notes = "查询指定分类下的所有菜品信息")
     @GetMapping("/cuisines")
     public R<List<StoreCuisine>> getCuisinesByCategoryId(

+ 17 - 0
alien-dining/src/main/java/shop/alien/dining/service/StoreInfoService.java

@@ -4,6 +4,7 @@ import shop.alien.entity.store.StoreCuisine;
 import shop.alien.entity.store.StoreCuisineCategory;
 import shop.alien.entity.store.StoreTable;
 import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
+import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
 
 import java.util.List;
 
@@ -40,6 +41,22 @@ public interface StoreInfoService {
     List<StoreCuisine> getCuisinesByCategoryId(Integer categoryId);
 
     /**
+     * 根据门店ID查询菜品种类及每个分类下的菜品列表(一次返回种类+菜品)
+     *
+     * @param storeId 门店ID
+     * @return 菜品种类及下属菜品列表
+     */
+    List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId);
+
+    /**
+     * 删除菜品种类:仅逻辑删除分类并解除菜品与该分类的绑定关系,价目表(菜品)本身不改动
+     *
+     * @param categoryId 菜品种类ID
+     * @return 是否成功
+     */
+    boolean deleteCategory(Integer categoryId);
+
+    /**
      * 根据商铺ID查询店铺信息和首页展示美食价目表信息
      *
      * @param storeId 商铺ID

+ 3 - 1
alien-dining/src/main/java/shop/alien/dining/service/impl/DiningServiceImpl.java

@@ -54,7 +54,9 @@ public class DiningServiceImpl implements DiningService {
         if (table == null) {
             return new TableDiningStatusVO(tableId, false, null);
         }
-        boolean inDining = Integer.valueOf(1).equals(table.getStatus())
+        // 就餐中(1)、加餐(3) 均视为就餐状态;且需已有就餐人数
+        Integer status = table.getStatus();
+        boolean inDining = (Integer.valueOf(1).equals(status) || Integer.valueOf(3).equals(status))
                 && table.getDinerCount() != null && table.getDinerCount() > 0;
         Integer dinerCount = inDining ? table.getDinerCount() : null;
         return new TableDiningStatusVO(tableId, inDining, dinerCount);

+ 97 - 1
alien-dining/src/main/java/shop/alien/dining/service/impl/StoreInfoServiceImpl.java

@@ -10,6 +10,7 @@ import shop.alien.entity.store.StoreCuisineCategory;
 import shop.alien.entity.store.StoreInfo;
 import shop.alien.entity.store.StoreTable;
 import shop.alien.entity.store.dto.StoreInfoWithHomepageCuisinesDTO;
+import shop.alien.entity.store.vo.CategoryWithCuisinesVO;
 import shop.alien.mapper.StoreCuisineCategoryMapper;
 import shop.alien.mapper.StoreCuisineMapper;
 import shop.alien.mapper.StoreInfoMapper;
@@ -19,6 +20,7 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 门店信息查询服务实现类
@@ -99,7 +101,101 @@ public class StoreInfoServiceImpl implements StoreInfoService {
                         return categoryIdsStr.contains(String.valueOf(categoryId));
                     }
                 })
-                .collect(java.util.stream.Collectors.toList());
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<CategoryWithCuisinesVO> getCategoriesWithCuisinesByStoreId(Integer storeId) {
+        log.info("根据门店ID查询菜品种类及下属菜品, storeId={}", storeId);
+        List<StoreCuisineCategory> categories = getCategoriesByStoreId(storeId);
+        if (categories == null || categories.isEmpty()) {
+            return new ArrayList<>();
+        }
+        LambdaQueryWrapper<StoreCuisine> cuisineWrapper = new LambdaQueryWrapper<>();
+        cuisineWrapper.eq(StoreCuisine::getStoreId, storeId);
+        cuisineWrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        cuisineWrapper.eq(StoreCuisine::getShelfStatus, 1);
+        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(cuisineWrapper);
+        if (allCuisines == null) {
+            allCuisines = new ArrayList<>();
+        }
+        List<CategoryWithCuisinesVO> result = new ArrayList<>();
+        for (StoreCuisineCategory category : categories) {
+            Integer categoryId = category.getId();
+            List<StoreCuisine> cuisines = allCuisines.stream()
+                    .filter(c -> belongsToCategory(c, categoryId))
+                    .collect(Collectors.toList());
+            result.add(new CategoryWithCuisinesVO(category, cuisines));
+        }
+        return result;
+    }
+
+    private boolean belongsToCategory(StoreCuisine cuisine, Integer categoryId) {
+        String categoryIdsStr = cuisine.getCategoryIds();
+        if (StringUtils.isBlank(categoryIdsStr)) {
+            return false;
+        }
+        try {
+            List<Integer> categoryIds = JSON.parseArray(categoryIdsStr, Integer.class);
+            return categoryIds != null && categoryIds.contains(categoryId);
+        } catch (Exception e) {
+            return categoryIdsStr.contains(String.valueOf(categoryId));
+        }
+    }
+
+    @Override
+    public boolean deleteCategory(Integer categoryId) {
+        log.info("删除菜品种类(仅解除绑定+逻辑删分类), categoryId={}", categoryId);
+        if (categoryId == null) {
+            log.warn("删除菜品种类失败:分类ID为空");
+            return false;
+        }
+        StoreCuisineCategory category = storeCuisineCategoryMapper.selectById(categoryId);
+        if (category == null) {
+            log.warn("删除菜品种类失败:分类不存在, categoryId={}", categoryId);
+            return false;
+        }
+        Integer storeId = category.getStoreId();
+        // 1. 解除绑定:将该分类ID从所有关联菜品的 category_ids 中移除,价目表菜品其它字段不变
+        LambdaQueryWrapper<StoreCuisine> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreCuisine::getStoreId, storeId);
+        wrapper.eq(StoreCuisine::getDeleteFlag, 0);
+        List<StoreCuisine> allCuisines = storeCuisineMapper.selectList(wrapper);
+        if (allCuisines != null) {
+            for (StoreCuisine cuisine : allCuisines) {
+                if (!belongsToCategory(cuisine, categoryId)) {
+                    continue;
+                }
+                String newCategoryIds = removeCategoryIdFromJson(cuisine.getCategoryIds(), categoryId);
+                cuisine.setCategoryIds(newCategoryIds);
+                storeCuisineMapper.updateById(cuisine);
+            }
+        }
+        // 2. 逻辑删除菜品种类
+        storeCuisineCategoryMapper.deleteById(categoryId);
+        log.info("删除菜品种类完成, categoryId={}", categoryId);
+        return true;
+    }
+
+    /** 从 categoryIds 的 JSON 数组中移除指定 categoryId,返回新 JSON 字符串;若为空则返回 null */
+    private String removeCategoryIdFromJson(String categoryIdsStr, Integer categoryId) {
+        if (StringUtils.isBlank(categoryIdsStr)) {
+            return null;
+        }
+        try {
+            List<Integer> list = JSON.parseArray(categoryIdsStr, Integer.class);
+            if (list == null || list.isEmpty()) {
+                return null;
+            }
+            list.remove(categoryId);
+            if (list.isEmpty()) {
+                return null;
+            }
+            return JSON.toJSONString(list);
+        } catch (Exception e) {
+            log.warn("解析 categoryIds 失败, categoryIdsStr={}, 原样返回", categoryIdsStr, e);
+            return categoryIdsStr;
+        }
     }
 
     @Override

+ 29 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/CategoryWithCuisinesVO.java

@@ -0,0 +1,29 @@
+package shop.alien.entity.store.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import shop.alien.entity.store.StoreCuisine;
+import shop.alien.entity.store.StoreCuisineCategory;
+
+import java.util.List;
+
+/**
+ * 菜品种类及其下属菜品 VO(通过门店ID查询时返回)
+ *
+ * @author system
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel(value = "CategoryWithCuisinesVO", description = "菜品种类及该分类下的菜品列表")
+public class CategoryWithCuisinesVO {
+
+    @ApiModelProperty(value = "菜品种类信息")
+    private StoreCuisineCategory category;
+
+    @ApiModelProperty(value = "该分类下的菜品列表")
+    private List<StoreCuisine> cuisines;
+}

+ 28 - 0
alien-store/src/main/java/shop/alien/store/controller/DiningServiceController.java

@@ -292,6 +292,34 @@ public class DiningServiceController {
         }
     }
 
+    @ApiOperation(value = "根据门店ID查询菜品种类及各类别下菜品", notes = "一次返回所有菜品种类及每个分类下的菜品列表")
+    @ApiOperationSupport(order = 11)
+    @GetMapping("/store/info/categories-with-cuisines")
+    public R<List<CategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
+            @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
+        try {
+            log.info("根据门店ID查询菜品种类及菜品: storeId={}", storeId);
+            return diningServiceFeign.getCategoriesWithCuisinesByStoreId(storeId);
+        } catch (Exception e) {
+            log.error("查询菜品种类及菜品失败: {}", e.getMessage(), e);
+            return R.fail("查询菜品种类及菜品失败: " + e.getMessage());
+        }
+    }
+
+    @ApiOperation(value = "删除菜品种类", notes = "仅删除绑定关系和菜品种类(逻辑删除);价目表菜品不变")
+    @ApiOperationSupport(order = 12)
+    @DeleteMapping("/store/info/category/{categoryId}")
+    public R<Boolean> deleteCategory(
+            @ApiParam(value = "菜品种类ID", required = true) @PathVariable Integer categoryId) {
+        try {
+            log.info("删除菜品种类: categoryId={}", categoryId);
+            return diningServiceFeign.deleteCategory(categoryId);
+        } catch (Exception e) {
+            log.error("删除菜品种类失败: {}", e.getMessage(), e);
+            return R.fail("删除菜品种类失败: " + e.getMessage());
+        }
+    }
+
     // ==================== 文件上传接口 ====================
 
     @ApiOperation(value = "上传图片到OSS", notes = "支持图片、视频或PDF文件上传,返回OSS文件路径")

+ 19 - 0
alien-store/src/main/java/shop/alien/store/feign/DiningServiceFeign.java

@@ -226,6 +226,25 @@ public interface DiningServiceFeign {
     R<List<StoreTable>> getTablesByStoreId(
             @RequestParam("storeId") Integer storeId);
 
+    /**
+     * 根据门店ID查询菜品种类及各类别下菜品
+     *
+     * @param storeId 门店ID
+     * @return R.data 为 List&lt;CategoryWithCuisinesVO&gt;
+     */
+    @GetMapping("/store/info/categories-with-cuisines")
+    R<List<CategoryWithCuisinesVO>> getCategoriesWithCuisinesByStoreId(
+            @RequestParam("storeId") Integer storeId);
+
+    /**
+     * 删除菜品种类(仅解除绑定+逻辑删分类,价目表菜品不变)
+     *
+     * @param categoryId 菜品种类ID
+     * @return R.data 为 Boolean
+     */
+    @DeleteMapping("/store/info/category/{categoryId}")
+    R<Boolean> deleteCategory(@PathVariable("categoryId") Integer categoryId);
+
     // ==================== 文件上传接口 ====================
 
     /**