毕设项目<<基于微信小程序的餐馆外卖系统>>(三)

毕设项目<<基于微信小程序的餐馆外卖系统的设计后端>>(开发记录(三)套餐管理)


视频传送带

套餐管理

1. 新增套餐

1.1 需求分析和设计
产品原型

请添加图片描述
请添加图片描述

业务规则
  • 套餐名称唯一
  • 套餐必须属于某个分类
  • 套餐必须包含菜品
  • 名称、分类、价格、图片为必填项
  • 添加菜品窗口需要根据分类类型来展示菜品
  • 新增的套餐默认为停售状态
接口设计(共涉及到4个接口)
  • 根据类型查询分类(已完成)
  • 根据分类id查询菜品
  • 图片上传(已完成)
  • 新增套餐
    请添加图片描述
    请添加图片描述
数据库设计

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<Dish>> list(Long categoryId){

    List<Dish> list = dishService.list(categoryId);

    return Result.success(list);

}

1.2.2 DishService

/**

     * 根据分类id查询菜品

     * @param categoryId

     * @return

*/

List<Dish> list(Long categoryId);

1.2.3 DishServiceImpl

/**

     * 根据分类id查询菜品

     * @param categoryId

     * @return

*/

public List<Dish> 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<Dish> list(Dish dish);

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

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

1.2.11 SetmealDishMapper

/**

     * 批量保存套餐和菜品的关联关系

     * @param setmealDishes

*/

void insertBatch(List<SetmealDish> setmealDishes);

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

功能测试

请添加图片描述

2. 套餐分页查询

2.1 需求分析和设计
产品原型

请添加图片描述

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

请添加图片描述

2.2 代码实现
2.2.1 SetmealController

/**

     * 分页查询

     * @param setmealPageQueryDTO

     * @return

*/

@GetMapping("/page")

@ApiOperation("分页查询")

public Result<PageResult> 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<SetmealVO> page = setmealMapper.pageQuery(setmealPageQueryDTO);

    return new PageResult(page.getTotal(), page.getResult());

}

2.2.4 SetmealMapper

/**

     * 分页查询

     * @param setmealPageQueryDTO

     * @return

*/

Page<SetmealVO> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);

2.2.5 SetmealMapper.xml

<select id="pageQuery" resultType="com.sky.vo.SetmealVO">

    select

        s.*,c.name categoryName

    from

        setmeal s

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

2.3 功能测试

请添加图片描述

3. 删除套餐

3.1 需求分析和设计
产品原型

请添加图片描述

业务规则
  • 可以一次删除一个套餐,也可以批量删除套餐
  • 起售中的套餐不能删除
接口设计

请添加图片描述

3.2 代码实现
3.2.1 SetmealController

/**

     * 批量删除套餐

     * @param ids

     * @return

*/

@DeleteMapping

@ApiOperation("批量删除套餐")

public Result delete(@RequestParam List<Long> ids){

    setmealService.deleteBatch(ids);

    return Result.success();

}

3.2.2 SetmealService

/**

     * 批量删除套餐

     * @param ids

*/

void deleteBatch(List<Long> ids);

3.2.3 SetmealServiceImpl

/**

     * 批量删除套餐

     * @param ids

*/

@Transactional

public void deleteBatch(List<Long> 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);

3.3 功能测试

请添加图片描述
请添加图片描述

4. 修改套餐

4.1 需求分析和设计
产品原型

请添加图片描述

接口设计(共涉及到5个接口)
  • 根据id查询套餐
  • 根据类型查询分类(已完成)
  • 根据分类id查询菜品(已完成)
  • 图片上传(已完成)
  • 修改套餐
    请添加图片描述
    请添加图片描述

请添加图片描述

请添加图片描述

请添加图片描述

4.2 代码实现
4.2.1 SetmealController

/**

     * 根据id查询套餐,用于修改页面回显数据

     *

     * @param id

     * @return

*/

@GetMapping("/{id}")

@ApiOperation("根据id查询套餐")

public Result<SetmealVO> 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<SetmealDish> 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<SetmealDish> 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<SetmealDish> getBySetmealId(Long setmealId);

4.3 功能测试

请添加图片描述

5. 起售停售套餐

5.1 需求分析和设计
产品原型:

请添加图片描述

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

请添加图片描述

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<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);
}
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<Dish> getBySetmealId(Long setmealId);
5.3 功能测试

请添加图片描述

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值