目录
1. 配送地址
1.1 新增地址
需要获取当前登录用户id,将该id与地址信息一起存进地址表中。
/**
* 新增地址
* @param addressBook
* @return
*/
@PostMapping
public R<String> save(@RequestBody AddressBook addressBook){
log.info("address:"+addressBook);
Long currentId = BaseContext.getCurrentId();
addressBook.setUserId(currentId);
addressBookService.save(addressBook);
return R.success("新增成功");
}
1.2 查询当前用户的全部地址
/**
* 根据用户id查询地址
* @return
*/
@GetMapping("/list")
public R<List<AddressBook>> list (){
//获取当前登录用户id
Long currentId = BaseContext.getCurrentId();
//查询该id下保存的所有地址信息
LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AddressBook::getUserId,currentId);
List<AddressBook> list = addressBookService.list(queryWrapper);
//返回给前端
return R.success(list);
}
1.3 设置默认地址
/**
* 设置默认地址
* @param addressBook
* @return
*/
@PutMapping("/default")
public R<AddressBook> setDefault(@RequestBody AddressBook addressBook){
//将当前用户的全部地址的idDefault字段更新为0,即全部设为非默认地址
LambdaUpdateWrapper<AddressBook> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(AddressBook::getUserId,BaseContext.getCurrentId());
updateWrapper.set(AddressBook::getIsDefault,0);
addressBookService.update(updateWrapper);
//通过id查询出该条地址,将其设为默认地址
addressBook.setIsDefault(1);
addressBookService.updateById(addressBook);
return R.success(addressBook);
}
2. 菜品展示
2.1 根据菜品分类展示菜品
修改DishController的list方法,因为需要返回菜品口味数据,所以需要将返回类型改为DishDto类型。
/**
* 根据分类id查询菜品
* @param dish
* @return
*/
@GetMapping("/list")
public R<List<DishDto>> getDishesByCategoryId(Dish dish){
//构造查询条件
LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
//添加条件,查询状态为1(起售状态)的菜品
queryWrapper.eq(Dish::getStatus,1);
//添加排序条件
queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
List<Dish> dishes = dishService.list(queryWrapper);
List<DishDto> dishDtos = dishes.stream().map((item)->{
DishDto dishDto = new DishDto();
BeanUtils.copyProperties(item,dishDto);
LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(DishFlavor::getDishId,item.getId());
List<DishFlavor> dishFlavors = dishFlavorService.list(lambdaQueryWrapper);
dishDto.setFlavors(dishFlavors);
return dishDto;
}).collect(Collectors.toList());
return R.success(dishDtos);
}
2.2 根据套餐分类展示套餐
/**
* 根据条件查询套餐信息
* @param setmeal
* @return
*/
@GetMapping("/list")
public R<List<Setmeal>> list(Setmeal setmeal){
LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(setmeal.getCategoryId()!=null,Setmeal::getCategoryId,setmeal.getCategoryId());
queryWrapper.eq(setmeal.getStatus()!=null,Setmeal::getStatus,setmeal.getStatus());
List<Setmeal> list = setmealService.list(queryWrapper);
return R.success(list);
}
3. 购物车
3.1 查看购物车
/**
* 查看购物车
* @return
*/
@GetMapping("/list")
public R<List<ShoppingCart>> list(){
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId, BaseContext.getCurrentId());
List<ShoppingCart> list = shoppingCartService.list(queryWrapper);
return R.success(list);
}
3.2 添加餐品到购物车
系统设计Bug:购物车中只含有createTime字段,而不含有updateTime等字段,所以公共数据自动填充无法正常执行,在该字段上添加 @TableField(fill = FieldFill.INSERT_UPDATE) 注解会报错,而不添加会导致该字段为空。
解决办法:加上 @TableField(fill = FieldFill.INSERT_UPDATE) 注解的同时,修改元数据对象处理器类(MyMetaObjectHandler.java)中的自动填充方法,在填充之前判断一下该字段是否存在,存在才填充:
/**
* 插入操作自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]"+metaObject.toString());
if (metaObject.hasSetter("createTime")){
metaObject.setValue("createTime",LocalDateTime.now());
}
if (metaObject.hasSetter("updateTime")){
metaObject.setValue("updateTime",LocalDateTime.now());
}
if (metaObject.hasSetter("createUser")){
metaObject.setValue("createUser",BaseContext.getCurrentId());
}
if (metaObject.hasSetter("updateUser")){
metaObject.setValue("updateUser",BaseContext.getCurrentId());
}
}
修改好之后可以正常实现添加餐品的业务逻辑了:
/**
* 添加餐品到购物车
* @param shoppingCart
* @return
*/
@PostMapping("/add")
public R<ShoppingCart> add(@RequestBody ShoppingCart shoppingCart){
//设置用户id
shoppingCart.setUserId(BaseContext.getCurrentId());
//查询当前菜品或套餐是否在购物车中
Long dishId = shoppingCart.getDishId();
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
if (dishId!=null){
//添加的是菜品则根据菜品id查询
queryWrapper.eq(ShoppingCart::getDishId,dishId);
}else {
//添加的是套餐则根据套餐id查询
queryWrapper.eq(ShoppingCart::getSetmealId,shoppingCart.getSetmealId());
}
//查询当前菜品或者套餐是否在购物车中
//SQL:select * from shopping_cart where user_id = ? and dish_id/setmeal_id = ?
ShoppingCart cartServiceOne = shoppingCartService.getOne(queryWrapper);
if (cartServiceOne!=null){
//如果存在,将数量加一
Integer number = cartServiceOne.getNumber();
cartServiceOne.setNumber(number+1);
shoppingCartService.updateById(cartServiceOne);
}else {
//如果不存在则新增
shoppingCart.setNumber(1);
shoppingCartService.save(shoppingCart);
cartServiceOne = shoppingCart;
}
//数据返回给前端
return R.success(cartServiceOne);
}
注:修改好的或者新增的一条购物车信息要返回给前端,特别要注意number字段是否有值,否则会出现点餐页面点击加号按钮餐品数量无法正常增加的情况。
3.3 清空购物车
/**
* 清空购物车
* @return
*/
@DeleteMapping("/clean")
public R<String> delete(){
//根据用户id清空购物车
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,BaseContext.getCurrentId());
shoppingCartService.remove(queryWrapper);
return R.success("清空成功!");
}
4. 下单
4.1 查询默认地址
@GetMapping("/default")
public R<AddressBook> getDefault(){
//根据用户id查询默认地址
LambdaQueryWrapper<AddressBook> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(AddressBook::getUserId,BaseContext.getCurrentId());
queryWrapper.eq(AddressBook::getIsDefault,1);
//SQL:select * from address_book where user_id = ? and is_default = 1
AddressBook addressBook = addressBookService.getOne(queryWrapper);
if (null == addressBook) {
return R.error("没有设置默认地址");
} else {
return R.success(addressBook);
}
}
4.2 下单
注:
1. 计算总价时使用 AtomicInteger 类型的数据对象,线程安全,保证在多线程高并发的情况下不会计算出错;使用 BigDecimal 精度更高。
AtomicInteger amount = new AtomicInteger(0);
amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
orders.setAmount(new BigDecimal(amount.get()));
2. 使用 IdWorker 生成订单id
long number = IdWorker.getId();
/**
* 下单
* @param orders
* @return
*/
@Transactional
@PostMapping("/submit")
public R<String> submit(@RequestBody Orders orders){
//获取当前用户id
Long userId = BaseContext.getCurrentId();
//查询当前用户的购物车数据
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId,userId);
List<ShoppingCart> shoppingCarts = shoppingCartService.list(queryWrapper);
//如果购物车为空,抛出一个业务异常
if(shoppingCarts == null || shoppingCarts.size() == 0){
throw new CustomException("购物车为空,不能下单");
}
//查询当前用户信息
User user = userService.getById(userId);
//查询地址信息
LambdaQueryWrapper<AddressBook> queryWrapper2 = new LambdaQueryWrapper<>();
queryWrapper2.eq(AddressBook::getId,orders.getAddressBookId());
AddressBook addressBook = addressBookService.getOne(queryWrapper2);
//生成订单号
long number = IdWorker.getId();
//创建AtomicInteger类型的数据对象,线程安全,保证在多线程高并发的情况下不会计算出错
AtomicInteger amount = new AtomicInteger(0);
//遍历购物车数据,设置订单详细信息
List<OrderDetail> orderDetails = shoppingCarts.stream().map((item)->{
OrderDetail orderDetail = new OrderDetail();
orderDetail.setOrderId(number); //设置订单号
orderDetail.setNumber(item.getNumber()); //设置餐品份数
orderDetail.setDishFlavor(item.getDishFlavor()); //设置口味
orderDetail.setDishId(item.getDishId());
orderDetail.setSetmealId(item.getSetmealId());
orderDetail.setName(item.getName()); //设置菜品名称
orderDetail.setImage(item.getImage()); //设置图片
orderDetail.setAmount(item.getAmount()); //设置单价
//计算订单总价,使用 BigDecimal 精度更高
amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
return orderDetail;
}).collect(Collectors.toList());
//向订单表插入数据,一条
orders.setId(number);
orders.setNumber(String.valueOf(number)); //设置订单号
orders.setOrderTime(LocalDateTime.now()); //设置下单时间
orders.setCheckoutTime(LocalDateTime.now()); //设置支付时间
orders.setUserId(userId); //设置下单用户id
orders.setUserName(user.getName()); //设置下单人姓名
orders.setAddress(addressBook.getDetail()); //设置地址
orders.setConsignee(addressBook.getConsignee()); //设置地址联系人姓名
orders.setPhone(addressBook.getPhone()); //设置地址联系人电话
orders.setAmount(new BigDecimal(amount.get())); //设置总价
orderService.save(orders);
//向订单明细表插入数据,多条
orderDetailService.saveBatch(orderDetails);
//清空购物车数据
shoppingCartService.remove(querywrapper);
return R.success("下单成功");
}