外卖项目day07---套餐管理

套餐管理模块所有业务功能包括:

新增套餐代码实现

套餐分页查询

删除套餐

修改套餐 

起售停售套餐



产品原型

业务规则:

- 套餐名称唯一

- 套餐必须属于某个分类

- 套餐必须包含菜品

- 名称、分类、价格、图片为必填项

- 添加菜品窗口需要根据分类类型来展示菜品

- 新增的套餐默认为停售状态


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

- 根据类型查询分类(已完成)

- 根据分类id查询菜品

- 图片上传(已完成)

- 新增套餐

数据库设计:

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           | 菜品份数 |          |

DishController中代码

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

 Dishservice新建接口

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    List<Dish> list(Long categoryId);

DishServiceImpl实体类重写接口中的方法

    /**
     * 根据分类id查询菜品
     * @param categoryId
     * @return
     */
    public List<Dish> list(Long categoryId) {
        Dish dish = Dish.builder()
                .status(StatusConstant.ENABLE)
                .categoryId(categoryId)
                .build();
        return dishMapper.list(dish);
    }

 DishMapper接口

    /**
     * 动态条件查询菜品
     * @param dish
     * @return
     */
    List<Dish> list(Dish dish);

 DishMapper.xml文件

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

测试,获取成功


新增套餐代码实现

SetmealController代码实现

@RestController
@RequestMapping("/admin/setmeal")
@Api(tags = "套餐相关接口")
@Slf4j
public class SetmealController {

    @Autowired
    private SetmealService setmealService;

    /**
     * 新增套餐
     * @param setmealDTO
     */
    @PostMapping
    @ApiOperation("新增套餐")
    public Result save(@RequestBody SetmealDTO setmealDTO){
        log.info("新增套餐:{}",setmealDTO);
        setmealService.saveWithDish(setmealDTO);
        return Result.success();


    }

}

SetmealService接口

public interface SetmealService {

    /**
     * 新增套餐,同时需要保存套餐和菜品的关联关系
     * @param setmealDTO
     */
    void saveWithDish(SetmealDTO setmealDTO);
}

SetmealServiceImpl实现类

/**
 * 套餐业务实现
 */
@Service
@Slf4j
public class SetmealServiceImpl implements SetmealService {

    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmealDishMapper setmealDishMapper;

    /**
     * 新增套餐,同时需要保存套餐和菜品的关联关系
     * @param setmealDTO
     */
    public void saveWithDish(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
        BeanUtils.copyProperties(setmealDTO,setmeal);

        //向套餐表插入数据
        setmealMapper.insert(setmeal);

        //获取生成的套餐id

        Long setmealId = setmeal.getId();
        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> {
            setmealDish.setSetmealId(setmealId);
        });

        //保存套餐和菜品的关联关系
        setmealDishMapper.insertBatch(setmealDishes);
    }
}

SetemealMapper接口新增方法

    /**
     * 向套餐表插入数据
     * @param setmeal
     */
    @AutoFill(OperationType.INSERT)
    void insert(Setmeal setmeal);

SetmealMapper.xml文件

    <insert id="insert" 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>

SetmealDishMapper接口新增方法

    /**
     * 批量保存套餐和菜品的关联关系
     * @param setmealDishes
     */
    void insertBatch(List<SetmealDish> setmealDishes);

SetmealDishMapper.xml

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

运行测试,前后端联调

查看数据库是否成功

新增菜品就成功了


套餐分页查询

产品原型

业务规则:

- 根据页码进行分页展示

- 每页展示10条数据

- 可以根据需要,按照套餐名称、分类、售卖状态进行查询


接口设计

SetmealController代码实现

    /**
     *套餐分页查询
     * @param setmealPageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("套餐分页查询")
    public Result<PageResult> page(SetmealPageQueryDTO setmealPageQueryDTO){
        log.info("套餐分页查询:{}",setmealPageQueryDTO);

        PageResult pageResult = setmealService.pageQuery(setmealPageQueryDTO);
        return Result.success(pageResult);
    }

SetmealService接口

    /**
     * 套餐分页查询
     * @param setmealPageQueryDTO
     * @return
     */
    PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);

SetmealServiceImpl实现类

    /**
     * 套餐分页查询
     * @param setmealPageQueryDTO
     * @return
     */
    public PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO) {

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

SetemealMapper接口新增方法

    /**
     * 套餐分页查询
     * @param setmealPageQueryDTO
     * @return
     */
    Page<SetmealVO> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);

SetmealMapper.xml文件

    <select id="pageQuery" resultType="com.sky.vo.SetmealVO">
        select s.*,c.name categoryName from setmeal s LEFT OUTER JOIN 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>

测试,成功显示分页界面


删除套餐

产品原型

业务规则:

- 可以一次删除一个套餐,也可以批量删除套餐

- 起售中的套餐不能删除


接口设计

SetmealController代码实现

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

SetmealService接口

    /**
     * 批量删除套餐
     * @param ids
     */
    void deleteBatch(List<Long> ids);

SetmealServiceImpl实现类

    /**
     * 批量删除套餐
     * @param ids
     */
    @Transactional
    public void deleteBatch(List<Long> ids) {
        ids.forEach(id -> {
            Setmeal setmeal = setmealMapper.getById(id);
            if(setmeal.getStatus() == StatusConstant.ENABLE){
                //起售中的套餐不能删除
                throw new DeletionNotAllowedException(MessageConstant.SETMEAL_ON_SALE);
            }
        });

        ids.forEach(setmealId -> {
            //删除套餐表中的数据
            setmealMapper.deleteById(setmealId);
            //删除套餐菜品关系表中的数据
            setmealDishMapper.deleteBysetmealId(setmealId);
        });

    }

SetemealMapper接口新增方法

    /**
     * 根据id查询套餐
     * @param id
     * @return
     */
    @Select("select * from setmeal where id = #{id}")
    Setmeal getById(Long id);

    /**
     * 根据id删除套餐
     * @param setmealId
     */
    @Delete("delete from setmeal where id = #{setmealId}")
    void deleteById(Long setmealId);

 SetmealDishMapper接口新增方法

    /**
     * 根据套餐id删除套餐和菜品的关联关系
     * @param setmealId
     */
    @Delete("delete from setmeal_dish where setmeal_id = #{setmealId}")
    void deleteBysetmealId(Long setmealId);

功能测试,测试成功~


修改套餐 

产品原型

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

- 根据id查询套餐

- 根据类型查询分类(已完成)

- 根据分类id查询菜品(已完成)

- 图片上传(已完成)

- 修改套餐

 SetmealController代码实现

    /**
     * 根据id查询套餐,用于修改页面回显数据
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询套餐")
    public Result<SetmealVO> getById(@PathVariable Long id){
        log.info("根据id查询套餐:{}",id);
        SetmealVO setmealVo = setmealService.getByIdWithDish(id);

        return Result.success(setmealVo);

    }
    /**
     * 修改套餐
     * @param setmealDTO
     */
    @PutMapping
    @ApiOperation("修改套餐")
    public Result update(@RequestBody SetmealDTO setmealDTO){
        log.info("修改套餐:{}",setmealDTO);
        setmealService.update(setmealDTO);
        return Result.success();
    }

SetmealService接口

    /**
     * 根据id查询套餐和关联的菜品数据
     * @param id
     * @return
     */
    SetmealVO getByIdWithDish(Long id);

    /**
     * 修改套餐
     * @param setmealDTO
     */
    void update(SetmealDTO setmealDTO);

SetmealServiceImpl实现类

    /**
     * 根据id查询套餐和套餐菜品关系
     * @param id
     * @return
     */
    public SetmealVO getByIdWithDish(Long id) {
        Setmeal setmeal = setmealMapper.getById(id);
        List<SetmealDish> setmealDishes = setmealDishMapper.getBySetmealId(id);

        SetmealVO setmealVO = new SetmealVO();
        BeanUtils.copyProperties(setmeal,setmealVO);
        setmealVO.setSetmealDishes(setmealDishes);
        return setmealVO;
    }

    /**
     * 修改套餐
     * @param setmealDTO
     */
    public void update(SetmealDTO setmealDTO) {
        Setmeal setmeal = new Setmeal();
         BeanUtils.copyProperties(setmealDTO,setmeal);


         // 修改套餐表,执行update
        setmealMapper.update(setmeal);

        Long setmealId = setmealDTO.getId();

        //删除套餐和菜品的关联关系,操作setmeal_dish表,执行delete
        setmealDishMapper.deleteBysetmealId(setmealId);

        List<SetmealDish> setmealDishes = setmealDTO.getSetmealDishes();
        setmealDishes.forEach(setmealDish -> {
            setmealDish.setSetmealId(setmealId);
        });
        //重新插入套餐和菜品的关联关系,操作setmeal_dish表,执行insert
        setmealDishMapper.insertBatch(setmealDishes);
    }

 SetmealDishMapper接口新增方法

    /**
     * 根据套餐id查询套餐和菜品的关联关系
     * @param setmealId
     */
    @Select("select * from setmeal_dish where setmeal_id = #{setmealId}")
    List<SetmealDish> getBySetmealId(Long setmealId););

功能测试,成功


起售停售套餐

产品原型

业务规则:

- 可以对状态为起售的套餐进行停售操作,可以对状态为停售的套餐进行起售操作

- 起售的套餐可以展示在用户端,停售的套餐不能展示在用户端

- 起售套餐时,如果套餐内包含停售的菜品,则不能起售

接口设计

  SetmealController代码实现

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

SetmealService接口

    /**
     * 套餐起售停售
     * @param status
     * @param id
     */
    void startOrStop(Integer status, Long id);
}

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<Dish> dishList = dishMapper.getBySetmealId(id);
            dishList.forEach(dish -> {
                if(dish.getStatus() == StatusConstant.DISABLE){
                    throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
                }
            });
        }

        Setmeal setmeal = Setmeal.builder()
                .id(id)
                .status(status)
                .build();
        setmealMapper.update(setmeal);
    }

DishMapper接口新增方法

    /**
     * 根据套餐id查询菜品
     * @param setmealId
     * @return
     */
    @Select("select d.* from dish d left join setmeal_dish s on d.id = s.dish_id where s.setmeal_id = #{setmealId}")
    List<Dish> getBySetmealId(Long setmealId);

功能测试

把菜品模块中的彩票停售,再测试套餐起售成功,套餐管理模块完成撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值