基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八)
作者:mmseoamin日期:2023-12-05

套餐模块功能开发

  • 1. 新增套餐
    • 1.1 需求分析和设计
      • 1.1.1产品原型:
      • 1.1.2接口设计:
      • 1.1.3数据库设计:
      • 1.2 代码开发
          • 1.2.1 DishController层
          • 1.2.2 DishService接口类
          • 1.2.3 DishServiceImpl接口实现类
          • 1.2.4 DishMapper层
          • 1.2.5 DishMapper.xml
          • 1.2.6 SetmealController层
          • 1.2.7 SetmealService接口类
          • 1.2.8 SetmealServiceImpl接口实现类
          • 1.2.9 SetmealMapper层
          • 1.2.10 SetmealMapper.xml
          • 1.2.11 SetmealDishMapper层
          • 1.2.12 SetmealDishMapper.xml
          • 2. 套餐分页查询
            • 2.1 需求分析和设计
              • 2.1.1产品原型:
              • 2.1.2接口设计:
              • 2.2 代码开发
                  • 2.2.1 SetmealController层
                  • 2.2.2 SetmealService接口类
                  • 2.2.3 SetmealServiceImpl接口实现类
                  • 2.2.4 SetmealMapper层
                  • 2.2.5 SetmealMapper.xml
                  • 3. 删除套餐
                    • 3.1 需求分析和设计
                      • 3.1.1产品原型:
                      • 3.1.2接口设计:
                      • 3.2 代码实现
                          • 3.2.1 SetmealController层
                          • 3.2.2 SetmealService接口类
                          • 3.2.3 SetmealServiceImpl接口实现类
                          • 3.2.4 SetmealMapper层
                          • 3.2.5 SetmealDishMapper
                          • 4. 修改套餐
                            • 4.1 需求分析和设计
                              • 4.1.1产品原型:
                              • 4.1.2接口设计(共涉及到5个接口):
                              • 4.2 代码实现
                                  • 4.2.1 SetmealController层
                                  • 4.2.2 SetmealService接口类
                                  • 4.2.3 SetmealServiceImpl接口实现类
                                  • 4.2.4 SetmealDishMapper层
                                  • 5. 起售停售套餐
                                    • 5.1 需求分析和设计
                                      • 5.1.1产品原型:
                                      • 5.1.2接口设计:
                                      • 5.2 代码实现
                                          • 5.2.1 SetmealController层
                                          • 5.2.2 SetmealService接口类
                                          • 5.2.3 SetmealServiceImpl接口实现类
                                          • 5.2.4 DishMapper层

                                            1. 新增套餐

                                            1.1 需求分析和设计

                                            1.1.1产品原型:

                                            基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第1张

                                            基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第2张

                                            业务规则:

                                            • 套餐名称唯一
                                            • 套餐必须属于某个分类
                                            • 套餐必须包含菜品
                                            • 名称、分类、价格、图片为必填项
                                            • 添加菜品窗口需要根据分类类型来展示菜品
                                            • 新增的套餐默认为停售状态

                                              接口设计(共涉及到4个接口):

                                              • 根据类型查询分类(已完成)
                                              • 根据分类id查询菜品
                                              • 图片上传(已完成)
                                              • 新增套餐

                                                1.1.2接口设计:

                                                基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第3张

                                                基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第4张

                                                1.1.3数据库设计:

                                                setmeal表为套餐表,用于存储套餐的信息。具体表结构如下:

                                                字段名数据类型说明备注
                                                idbigint主键自增
                                                namevarchar(32)套餐名称唯一
                                                category_idbigint分类id逻辑外键
                                                pricedecimal(10,2)套餐价格
                                                imagevarchar(255)图片路径
                                                descriptionvarchar(255)套餐描述
                                                statusint售卖状态1起售 0停售
                                                create_timedatetime创建时间
                                                update_timedatetime最后修改时间
                                                create_userbigint创建人id
                                                update_userbigint最后修改人id

                                                setmeal_dish表为套餐菜品关系表,用于存储套餐和菜品的关联关系。具体表结构如下:

                                                字段名数据类型说明备注
                                                idbigint主键自增
                                                setmeal_idbigint套餐id逻辑外键
                                                dish_idbigint菜品id逻辑外键
                                                namevarchar(32)菜品名称冗余字段
                                                pricedecimal(10,2)菜品单价冗余字段
                                                copiesint菜品份数

                                                1.2 代码开发

                                                1.2.1 DishController层
                                                /**
                                                     * 根据分类id查询菜品
                                                     * @param categoryId
                                                     * @return
                                                */
                                                @GetMapping("/list")
                                                @ApiOperation("根据分类id查询菜品")
                                                public Result> list(Long categoryId){
                                                    List list = dishService.list(categoryId);
                                                    return Result.success(list);
                                                }
                                                
                                                1.2.2 DishService接口类
                                                /**
                                                     * 根据分类id查询菜品
                                                     * @param categoryId
                                                     * @return
                                                */
                                                List list(Long categoryId);
                                                
                                                1.2.3 DishServiceImpl接口实现类
                                                /**
                                                     * 根据分类id查询菜品
                                                     * @param categoryId
                                                     * @return
                                                */
                                                public List list(Long categoryId) {
                                                    Dish dish = Dish.builder()
                                                        .categoryId(categoryId)
                                                        .status(StatusConstant.ENABLE)
                                                        .build();
                                                    return dishMapper.list(dish);
                                                }
                                                
                                                1.2.4 DishMapper层
                                                /**
                                                     * 动态条件查询菜品
                                                     * @param dish
                                                     * @return
                                                */
                                                List list(Dish dish);
                                                
                                                1.2.5 DishMapper.xml
                                                
                                                
                                                1.2.6 SetmealController层
                                                /**
                                                 * 套餐管理
                                                 */
                                                @RestController
                                                @RequestMapping("/admin/setmeal")
                                                @Api(tags = "套餐相关接口")
                                                @Slf4j
                                                public class SetmealController {
                                                    @Autowired
                                                    private SetmealService setmealService;
                                                    /**
                                                     * 新增套餐
                                                     * @param setmealDTO
                                                     * @return
                                                     */
                                                    @PostMapping
                                                    @ApiOperation("新增套餐")
                                                    public Result save(@RequestBody SetmealDTO setmealDTO) {
                                                        setmealService.saveWithDish(setmealDTO);
                                                        return Result.success();
                                                    }
                                                }
                                                
                                                1.2.7 SetmealService接口类
                                                public interface SetmealService {
                                                    /**
                                                     * 新增套餐,同时需要保存套餐和菜品的关联关系
                                                     * @param setmealDTO
                                                     */
                                                    void saveWithDish(SetmealDTO setmealDTO);
                                                }
                                                
                                                1.2.8 SetmealServiceImpl接口实现类
                                                /**
                                                 * 套餐业务实现
                                                 */
                                                @Service
                                                @Slf4j
                                                public class SetmealServiceImpl implements SetmealService {
                                                    @Autowired
                                                    private SetmealMapper setmealMapper;
                                                    @Autowired
                                                    private SetmealDishMapper setmealDishMapper;
                                                    @Autowired
                                                    private DishMapper dishMapper;
                                                    /**
                                                     * 新增套餐,同时需要保存套餐和菜品的关联关系
                                                     * @param setmealDTO
                                                     */
                                                    @Transactional
                                                    public void saveWithDish(SetmealDTO setmealDTO) {
                                                        Setmeal setmeal = new Setmeal();
                                                        BeanUtils.copyProperties(setmealDTO, setmeal);
                                                        //向套餐表插入数据
                                                        setmealMapper.insert(setmeal);
                                                        //获取生成的套餐id
                                                        Long setmealId = setmeal.getId();
                                                        List setmealDishes = setmealDTO.getSetmealDishes();
                                                        setmealDishes.forEach(setmealDish -> {
                                                            setmealDish.setSetmealId(setmealId);
                                                        });
                                                        //保存套餐和菜品的关联关系
                                                        setmealDishMapper.insertBatch(setmealDishes);
                                                    }
                                                }
                                                
                                                1.2.9 SetmealMapper层
                                                /**
                                                     * 新增套餐
                                                     * @param setmeal
                                                */
                                                @AutoFill(OperationType.INSERT)
                                                void insert(Setmeal setmeal);
                                                
                                                1.2.10 SetmealMapper.xml
                                                
                                                    insert into setmeal
                                                    (category_id, name, price, status, description, image, create_time, update_time, create_user, update_user)
                                                    values (#{categoryId}, #{name}, #{price}, #{status}, #{description}, #{image}, #{createTime}, #{updateTime},
                                                    #{createUser}, #{updateUser})
                                                
                                                
                                                1.2.11 SetmealDishMapper层
                                                /**
                                                     * 批量保存套餐和菜品的关联关系
                                                     * @param setmealDishes
                                                */
                                                void insertBatch(List setmealDishes);
                                                
                                                1.2.12 SetmealDishMapper.xml
                                                
                                                    insert into setmeal_dish
                                                    (setmeal_id,dish_id,name,price,copies)
                                                    values
                                                    
                                                        (#{sd.setmealId},#{sd.dishId},#{sd.name},#{sd.price},#{sd.copies})
                                                    
                                                
                                                

                                                2. 套餐分页查询

                                                2.1 需求分析和设计

                                                2.1.1产品原型:

                                                基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第5张

                                                业务规则:

                                                • 根据页码进行分页展示
                                                • 每页展示10条数据
                                                • 可以根据需要,按照套餐名称、分类、售卖状态进行查询

                                                  2.1.2接口设计:

                                                  基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第6张

                                                  2.2 代码开发

                                                  2.2.1 SetmealController层
                                                  /**
                                                       * 分页查询
                                                       * @param setmealPageQueryDTO
                                                       * @return
                                                  */
                                                  @GetMapping("/page")
                                                  @ApiOperation("分页查询")
                                                  public Result page(SetmealPageQueryDTO setmealPageQueryDTO) {
                                                      PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
                                                      return Result.success(pageResult);
                                                  }
                                                  
                                                  2.2.2 SetmealService接口类
                                                  /**
                                                       * 分页查询
                                                       * @param setmealPageQueryDTO
                                                       * @return
                                                  */
                                                  PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
                                                  
                                                  2.2.3 SetmealServiceImpl接口实现类
                                                  /**
                                                       * 分页查询
                                                       * @param setmealPageQueryDTO
                                                       * @return
                                                  */
                                                  public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {
                                                      int pageNum = setmealPageQueryDTO.getPage();
                                                      int pageSize = setmealPageQueryDTO.getPageSize();
                                                      PageHelper.startPage(pageNum, pageSize);
                                                      Page page = setmealMapper.pageQuery(setmealPageQueryDTO);
                                                      return new PageResult(page.getTotal(), page.getResult());
                                                  }
                                                  
                                                  2.2.4 SetmealMapper层
                                                  /**
                                                       * 分页查询
                                                       * @param setmealPageQueryDTO
                                                       * @return
                                                  */
                                                  Page pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
                                                  
                                                  2.2.5 SetmealMapper.xml
                                                  
                                                  

                                                  3. 删除套餐

                                                  3.1 需求分析和设计

                                                  3.1.1产品原型:

                                                  基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第7张

                                                  业务规则:

                                                  • 可以一次删除一个套餐,也可以批量删除套餐
                                                  • 起售中的套餐不能删除

                                                    3.1.2接口设计:

                                                    基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第8张

                                                    3.2 代码实现

                                                    3.2.1 SetmealController层
                                                    /**
                                                         * 批量删除套餐
                                                         * @param ids
                                                         * @return
                                                    */
                                                    @DeleteMapping
                                                    @ApiOperation("批量删除套餐")
                                                    public Result delete(@RequestParam List ids){
                                                        setmealService.deleteBatch(ids);
                                                        return Result.success();
                                                    }
                                                    
                                                    3.2.2 SetmealService接口类
                                                    /**
                                                         * 批量删除套餐
                                                         * @param ids
                                                    */
                                                    void deleteBatch(List ids);
                                                    
                                                    3.2.3 SetmealServiceImpl接口实现类
                                                    /**
                                                         * 批量删除套餐
                                                         * @param ids
                                                    */
                                                    @Transactional
                                                    public void deleteBatch(List ids) {
                                                        ids.forEach(id -> {
                                                            Setmeal setmeal = setmealMapper.getById(id);
                                                            if(StatusConstant.ENABLE == setmeal.getStatus()){
                                                                //起售中的套餐不能删除
                                                                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
                                                            }
                                                        });
                                                        ids.forEach(setmealId -> {
                                                            //删除套餐表中的数据
                                                            setmealMapper.deleteById(setmealId);
                                                            //删除套餐菜品关系表中的数据
                                                            setmealDishMapper.deleteBySetmealId(setmealId);
                                                        });
                                                    }
                                                    
                                                    3.2.4 SetmealMapper层
                                                    /**
                                                         * 根据id查询套餐
                                                         * @param id
                                                         * @return
                                                    */
                                                    @Select("select * from setmeal where id = #{id}")
                                                    Setmeal getById(Long id);
                                                    /**
                                                         * 根据id删除套餐
                                                         * @param setmealId
                                                    */
                                                    @Delete("delete from setmeal where id = #{id}")
                                                    void deleteById(Long setmealId);
                                                    
                                                    3.2.5 SetmealDishMapper
                                                    /**
                                                         * 根据套餐id删除套餐和菜品的关联关系
                                                         * @param setmealId
                                                    */
                                                    @Delete("delete from setmeal_dish where setmeal_id = #{setmealId}")
                                                    void deleteBySetmealId(Long setmealId);
                                                    

                                                    4. 修改套餐

                                                    4.1 需求分析和设计

                                                    4.1.1产品原型:

                                                    基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第9张

                                                    4.1.2接口设计(共涉及到5个接口):

                                                    • 根据id查询套餐
                                                    • 根据类型查询分类(已完成)
                                                    • 根据分类id查询菜品(已完成)
                                                    • 图片上传(已完成)
                                                    • 修改套餐

                                                      基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第10张

                                                      基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第11张

                                                      基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第12张

                                                      基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第13张

                                                      基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第14张

                                                      4.2 代码实现

                                                      4.2.1 SetmealController层
                                                      /**
                                                           * 根据id查询套餐,用于修改页面回显数据
                                                           *
                                                           * @param id
                                                           * @return
                                                      */
                                                      @GetMapping("/{id}")
                                                      @ApiOperation("根据id查询套餐")
                                                      public Result getById(@PathVariable Long id) {
                                                          SetmealVO setmealVO = setmealService.getByIdWithDish(id);
                                                          return Result.success(setmealVO);
                                                      }
                                                      /**
                                                           * 修改套餐
                                                           *
                                                           * @param setmealDTO
                                                           * @return
                                                      */
                                                      @PutMapping
                                                      @ApiOperation("修改套餐")
                                                      public Result update(@RequestBody SetmealDTO setmealDTO) {
                                                          setmealService.update(setmealDTO);
                                                          return Result.success();
                                                      }
                                                      
                                                      4.2.2 SetmealService接口类
                                                      /**
                                                           * 根据id查询套餐和关联的菜品数据
                                                           * @param id
                                                           * @return
                                                      */
                                                      SetmealVO getByIdWithDish(Long id);
                                                      /**
                                                           * 修改套餐
                                                           * @param setmealDTO
                                                      */
                                                      void update(SetmealDTO setmealDTO);
                                                      
                                                      4.2.3 SetmealServiceImpl接口实现类
                                                      /**
                                                           * 根据id查询套餐和套餐菜品关系
                                                           *
                                                           * @param id
                                                           * @return
                                                      */
                                                      public SetmealVO getByIdWithDish(Long id) {
                                                          Setmeal setmeal = setmealMapper.getById(id);
                                                          List setmealDishes = setmealDishMapper.getBySetmealId(id);
                                                          SetmealVO setmealVO = new SetmealVO();
                                                          BeanUtils.copyProperties(setmeal, setmealVO);
                                                          setmealVO.setSetmealDishes(setmealDishes);
                                                          
                                                          return setmealVO;
                                                      }
                                                      /**
                                                           * 修改套餐
                                                           *
                                                           * @param setmealDTO
                                                      */
                                                      @Transactional
                                                      public void update(SetmealDTO setmealDTO) {
                                                          Setmeal setmeal = new Setmeal();
                                                          BeanUtils.copyProperties(setmealDTO, setmeal);
                                                          //1、修改套餐表,执行update
                                                          setmealMapper.update(setmeal);
                                                          //套餐id
                                                          Long setmealId = setmealDTO.getId();
                                                          //2、删除套餐和菜品的关联关系,操作setmeal_dish表,执行delete
                                                          setmealDishMapper.deleteBySetmealId(setmealId);
                                                          List setmealDishes = setmealDTO.getSetmealDishes();
                                                          setmealDishes.forEach(setmealDish -> {
                                                              setmealDish.setSetmealId(setmealId);
                                                          });
                                                          //3、重新插入套餐和菜品的关联关系,操作setmeal_dish表,执行insert
                                                          setmealDishMapper.insertBatch(setmealDishes);
                                                      }
                                                      
                                                      4.2.4 SetmealDishMapper层
                                                      	/**
                                                           * 根据套餐id查询套餐和菜品的关联关系
                                                           * @param setmealId
                                                           * @return
                                                           */
                                                          @Select("select * from setmeal_dish where setmeal_id = #{setmealId}")
                                                          List getBySetmealId(Long setmealId);
                                                      

                                                      5. 起售停售套餐

                                                      5.1 需求分析和设计

                                                      5.1.1产品原型:

                                                      基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第15张

                                                      业务规则:

                                                      • 可以对状态为起售的套餐进行停售操作,可以对状态为停售的套餐进行起售操作
                                                      • 起售的套餐可以展示在用户端,停售的套餐不能展示在用户端
                                                      • 起售套餐时,如果套餐内包含停售的菜品,则不能起售

                                                        5.1.2接口设计:

                                                        基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(八),在这里插入图片描述,第16张

                                                        5.2 代码实现

                                                        5.2.1 SetmealController层
                                                        /**
                                                             * 套餐起售停售
                                                             * @param status
                                                             * @param id
                                                             * @return
                                                        */
                                                        @PostMapping("/status/{status}")
                                                        @ApiOperation("套餐起售停售")
                                                        public Result startOrStop(@PathVariable Integer status, Long id) {
                                                            setmealService.startOrStop(status, id);
                                                            return Result.success();
                                                        }
                                                        
                                                        5.2.2 SetmealService接口类
                                                        /**
                                                             * 套餐起售、停售
                                                             * @param status
                                                             * @param id
                                                        */
                                                        void startOrStop(Integer status, Long id);
                                                        
                                                        5.2.3 SetmealServiceImpl接口实现类
                                                        /**
                                                             * 套餐起售、停售
                                                             * @param status
                                                             * @param id
                                                        */
                                                        public void startOrStop(Integer status, Long id) {
                                                            //起售套餐时,判断套餐内是否有停售菜品,有停售菜品提示"套餐内包含未启售菜品,无法启售"
                                                            if(status == StatusConstant.ENABLE){
                                                                //select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = ?
                                                                List dishList = dishMapper.getBySetmealId(id);
                                                                if(dishList != null && dishList.size() > 0){
                                                                    dishList.forEach(dish -> {
                                                                        if(StatusConstant.DISABLE == dish.getStatus()){
                                                                            throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
                                                                        }
                                                                    });
                                                                }
                                                            }
                                                            Setmeal setmeal = Setmeal.builder()
                                                                .id(id)
                                                                .status(status)
                                                                .build();
                                                            setmealMapper.update(setmeal);
                                                        }
                                                        
                                                        5.2.4 DishMapper层
                                                        /**
                                                             * 根据套餐id查询菜品
                                                             * @param setmealId
                                                             * @return
                                                        */
                                                        @Select("select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = #{setmealId}")
                                                        List getBySetmealId(Long setmealId);
                                                        

                                                        后记

                                                        👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹