苍穹外卖day4 套餐管理


前言

套餐管理这部分主要涉及到的数据库表包括套餐表(setmeal)和菜品表(dish)以及一种套餐关联的所有菜品表(setmeal_dish),业务功能包括新增套餐、套餐分页查询、删除套餐、修改套餐、套餐起售停售。


一、新增套餐

1. 业务规则

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

2. 接口设计

  • 根据套餐类型查询分类(已完成)
  • 根据分类id查询菜品
  • 图片上传(已完成)
  • 新增套餐
    在这里插入图片描述
    在这里插入图片描述

3.数据库设计

setmeal表为套餐表,用于存储套餐的信息。具体表结构如下:
| 字段名      | 数据类型      | 说明         | 备注        |
| ----------- | ------------- | ------------| -----------|
| id          | bigint        | 主键         | 自增        |
| name        | varchar(32)   | 套餐名称     | 唯一        |
| category_id | bigint        | 分类id       | 逻辑外键    |
| price       | decimal(10,2) | 套餐价格     |             |
| image       | varchar(255)  | 图片路径     |             |
| description | varchar(255)  | 套餐描述     |             |
| status      | int           | 售卖状态     | 1起售 0停售 |
| create_time | datetime      | 创建时间     |             |
| update_time | datetime      | 最后修改时间 |             |
| create_user | bigint        | 创建人id     |             |
| update_user | bigint        | 最后修改人id |             |

setmeal_dish表为套餐菜品关系表,用于存储套餐和菜品的关联关系。具体表结构如下:
| 字段名     | 数据类型      | 说明     | 备注     |
| ---------- | ------------- | -------- | -------- |
| id         | bigint        | 主键     | 自增     |
| setmeal_id | bigint        | 套餐id   | 逻辑外键 |
| dish_id    | bigint        | 菜品id   | 逻辑外键 |
| name       | varchar(32)   | 菜品名称 | 冗余字段 |
| price      | decimal(10,2) | 菜品单价 | 冗余字段 |
| copies     | int           | 菜品份数 |          |

4. 代码实现

4.1 根据套餐类型查询菜品

1、在DishController中定义方法,用于为套餐添加菜品时使用
在这里插入图片描述

@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<Dish>> list(Long categoryId){
    List<Dish> list = dishService.list(categoryId);
    return Result.success(list);
}

2、在DishService中定义list方法,在DishServiceImpl中实现业务逻辑

public List<Dish> list(Long categoryId) {
    Dish dish = Dish.builder()
        .categoryId(categoryId)
        .status(StatusConstant.ENABLE)
        .build();
    return dishMapper.list(dish);
}

3、在DishMapper中定义方法,动态条件查询菜品

<select id="list" resultType="Dish" parameterType="Dish">
    select * from dish
    <where>
        <if test="name != null">and name like concat('%',#{name},'%') </if>
        <if test="categoryId != null">and category_id = #{categoryId}</if>
        <if test="status != null">and status = #{status}</if>
    </where>
    order by create_time desc
</select>

4.2 新增套餐

1、在SetmealController中定义方法

    @PostMapping
    @ApiOperation("新增套餐")
    public Result saveSetmealwithDish(@RequestBody SetmealDTO setmealDTO){
        setmealService.saveSetmealwithDish(setmealDTO);
        return Result.success();
    }

2、在SetmealService中定义saveSetmealwithDish方法,新增套餐,同时需要保存套餐和菜品的关联关系,在SetmealServiceImpl中实现方法

    @Transactional  //多表操作,开启事务注解
    public void saveSetmealwithDish(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO, setmeal);
        //1、向套餐表插入数据
        setmealMapper.insert(setmeal);
        //2、获取生成的套餐id
        Long setmealId = setmeal.getId();
        //获取这个套餐下所关联的所有菜品
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> {
            //把套餐id存入套餐_菜品表中
            setmealDish.setSetmealId(setmealId);
        });
        //保存套餐和菜品的关联关系
        setmealDishMapper.insertBatch(setmealDishes);
    }

3、在SetmealMapper中编写方法新增套餐,在SetmealMapper.xml中编写sql语句

@AutoFill(OperationType.INSERT)
void insert(Setmeal setmeal);
<insert id="insert" parameterType="Setmeal" useGeneratedKeys="true" keyProperty="id">
    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})
</insert>

4、在SetmealDishMapper中编写方法批量保存套餐和菜品的关联关系,在SetmealDishMapper.xml中编写sql语句

<insert id="insertBatch" parameterType="list">
    insert into setmeal_dish
    (setmeal_id,dish_id,name,price,copies)
    values
    <foreach collection="setmealDishes" item="sd" separator=",">
        (#{sd.setmealId},#{sd.dishId},#{sd.name},#{sd.price},#{sd.copies})
    </foreach>
</insert>

二、套餐分页查询

1. 业务规则

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

2. 接口设计

在这里插入图片描述

3.代码实现

1、在SetmealController中编写方法

@GetMapping("/page")
  @ApiOperation("分页查询套餐信息")
  public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO){
      log.info("套餐分页查询:{}",setmealPageQueryDTO);
      PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
      return Result.success(pageResult);
  }

2、在SetmealService定义pageQuery方法,在SetmealServiceImpl中实现

public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {
   PageHelper.startPage(setmealPageQueryDTO.getPage(),setmealPageQueryDTO.getPageSize());
   Page<SetmealVO> page = setmealMapper.pageQuery(setmealPageQueryDTO);
   return new PageResult(page.getTotal(),page.getResult());
}

3、在SetmealMapper中定义方法,在SetmealMapper.xml中编写sql语句查询套餐信息。返回的参数类型是setmealvo对象,关联了两张表的信息,要进行多表联查。

<select id="pageQuery" resultType="com.sky.vo.SetmealVO">
    select s.*,c.name categoryName from sky_take_out.setmeal s 
    left join sky_take_out.category c on s.category_id = c.id
    <where>
        <if test="name != null">and s.name like concat('%',#{name},'%') </if>
        <if test="status != null">and s.status = #{status} </if>
        <if test="categoryId != null">and s.category_id = #{categoryId}</if>
    </where>
    order by s.create_time desc
</select>

三、删除套餐

1. 业务规则

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

2. 接口设计

在这里插入图片描述

3. 代码实现

1、在SetmealController中编写方法,根据前端响应过来的套餐id

    @DeleteMapping
    @ApiOperation("批量删除套餐")
    public Result delete(@RequestParam List<Long> ids){
        setmealService.deleteBatch(ids);
        return Result.success();
    }

2、在SetmealService定义方法,在SetmealServiceImpl中实现方法

 @Transactional
    public void deleteBatch(List<Long> ids) {
        //判断当前套餐是否能够删除--是否存在起售中的套餐 status
        for (Long id : ids) {
            Setmeal setmeal = setmealMapper.getById(id);
            if(setmeal.getStatus() == StatusConstant.ENABLE){//当前菜品处于起售中,不能删除
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        }
        //批量删除套餐
        setmealMapper.deleteByIds(ids);
        //还要删除套餐关联的菜品信息
        setmealDishMapper.deleteBysetmealIds(ids);
    }

3、在SetmealMapper定义getByI方法,根据id查询套餐

@Select("select * from setmeal where id = #{id}")
Setmeal getById(Long id);

4、在SetmealMapper定义deleteByIds方法,在SetmealMappe.xml中编写sql语句批量删除套餐

<delete id="deleteByIds">
        delete from sky_take_out.setmeal where id in
        <foreach collection="ids" item="id" open="(" close=")">#{id}</foreach>
</delete>

5、在SetmealDishMapper定义deleteBysetmealIds方法,在SetmealMappe.xml中编写sql语句批量删除套餐关联的菜品信息

<delete id="deleteBysetmealIds">
        delete from sky_take_out.setmeal_dish where setmeal_id in
        <foreach collection="setmealIds" item="sid" open="(" close=")">#{sid}</foreach>
</delete>

四、修改套餐

1. 接口设计

  • 根据id查询套餐(信息回显)
  • 根据类型查询分类(已完成)
  • 根据分类id查询菜品(已完成)
  • 图片上传(已完成)
  • 修改套餐
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2. 代码实现

2.1 根据id查询套餐

1、在SetmealController定义getById方法

@GetMapping("/{id}")
@ApiOperation("根据套餐id查询套餐")
public Result<SetmealVO> getById(@PathVariable Long id){
    SetmealVO setmealVO = setmealService.getByIdWithDish(id);
    return Result.success(setmealVO);
}

2、在SetmealService中定义getByIdWithDish方法,在getByIdWithDishImpl中实现

 public SetmealVO getByIdWithDish(Long id) {
        //根据id查询套餐信息
        Setmeal setmeal = setmealMapper.getById(id);
        SetmealVO setmealVO = new SetmealVO();
        BeanUtils.copyProperties(setmeal,setmealVO);
        //根据套餐id查询对应的菜品信息
        List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(setmeal.getId());
        setmealVO.setSetmealDishes(setmealDishes);
        return setmealVO;
    }

3、在SetmealMapper中定义getById方法

 @Select("select * from sky_take_out.setmeal where id = #{id}")
Setmeal getById(Long id);

4、在SetmealDishMapper中定义getBySetmealId方法

@Select("select * from sky_take_out.setmeal_dish where setmeal_id=#{setmealId}")
List<SetmealDish> getBySetmealId(Long setmealId);

2.2 修改套餐

1、在SetmealController定义update方法

@PutMapping
@ApiOperation("修改套餐")
public Result update(@RequestBody SetmealDTO setmealDTO) {
    setmealService.updateWithDish(setmealDTO);
    return Result.success();

2、在SetmealService中定义updateWithDish方法,在getByIdWithDishImpl中实现

@Transactional
    public void updateWithDish(SetmealDTO setmealDTO) {
        //1.修改套餐的基本信息
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO,setmeal);
        setmealMapper.update(setmeal);
        //2 删除套餐和菜品的关联关系,操作setmeal_dish表,执行delete
        Long setmealId = setmeal.getId();  //得到套餐id
        setmealDishMapper.deleteBysetmealId(setmealId);
        //3 插入新的套餐和菜品的关联关系,操作setmeal_dish表,执行insert
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> {
            setmealDish.setSetmealId(setmealId);
        });
        setmealDishMapper.insertBatch(setmealDishes);
    }

3、在SetmealMapper中定义update方法,在SetmealMapper.xml中编写sql语句

 <update id="update">
     update sky_take_out.setmeal
     <set>
         <if test="name != null">name = #{name},</if>
         <if test="categoryId != null">category_id = #{categoryId},</if>
         <if test="price != null">price = #{price},</if>
         <if test="image != null">image = #{image},</if>
         <if test="description != null">description = #{description},</if>
         <if test="status != null">status = #{status},</if>
         <if test="updateTime != null">update_time = #{updateTime},</if>
         <if test="updateUser != null">update_user = #{updateUser},</if>
     </set>
     where id = #{id}
 </update>

3、在SetmealDishMapper中定义deleteBysetmealId方法和insertBatch方法,在SetmealDishMapper.xml中编写sql语句

//删除单个与套餐有关联的菜品信息
@Delete("delete from sky_take_out.setmeal_dish where setmeal_id = #{setmealId};")
void deleteBysetmealId(Long setmealId);
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="id">
    insert into sky_take_out.setmeal_dish(setmeal_id, dish_id, name, price, copies VALUES
        <foreach collection="setmealDishes" item="sd" separator=",">
            (#{sd.setmealId}, #{sd.dishId}, #{sd.name}, #{sd.price}, #{sd.copies})
        </foreach>
</insert>

五、起售停售套餐

1. 业务规则

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

2. 接口设计

在这里插入图片描述

3. 代码实现

1、在SetmealController编写startOrStop方法

 @PostMapping("/status/{status}")
 @ApiOperation("套餐起售停售")
 public Result startOrStop(@PathVariable Integer status,Long id ){
     setmealService.startOrStop(id,status);
     return Result.success();
 }

2、在SetmealService中定义startOrStop方法,在startOrStopImpl中实现

public void startOrStop(Long id, Integer status) {
//起售套餐时,判断套餐内是否有停售的菜品,有停售的菜品提示"套餐内包含未启售菜品,无法启售
	if(status == StatusConstant.ENABLE){
	//通过套餐id得到菜品信息
	   List<Dish> 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);
}

3、在DishMapper中定义getBySetmealId方法,根据套餐id查询菜品

@Select("select a.* from dish a left join setmeal_dish b on a.id = b.dish_id where b.setmeal_id = #{setmealId}")
List<Dish> getBySetmealId(Long setmealId);
  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值