微信点餐系统(二)买家订单操作
买家端的订单操作主要有创建订单,查看订单,查看订单详情,取消订单四个操作。
一、创建订单
1.查看API文档
###创建订单
```
POST /sell/buyer/order/create
```
参数
```
name: "张三"
phone: "18868822111"
address: "慕课网总部"
openid: "ew3euwhd7sjw9diwkq" //用户的微信openid
items: [{
productId: "1423113435324",
productQuantity: 2 //购买数量
}]
```
返回
```
{
"code": 0,
"msg": "成功",
"data": {
"orderId": "147283992738221"
}
}
```
根据API文档可以知道前端发送的请求是POST请求,请求路径是 /sell/buyer/order/create
根据文档中传入参数编写一个OrderForm类,接收前端传入数据。注意传入有关订单部分的数据items是个列表,每个元素只有productId和productQuantity,而没有有关价格、库存等其它数据,这是为了保证安全性。这些字段还要求非空否则就会报错。
1 package club.nipengfei.sell1.form; 2 3 import lombok.Data; 4 import javax.validation.constraints.NotEmpty; 5 6 @Data 7 public class OrderForm { 8 @NotEmpty(message = "姓名必填") 9 private String name; 10 11 @NotEmpty(message = "手机号必填") 12 private String phone; 13 14 @NotEmpty(message = "地址必填") 15 private String address; 16 17 @NotEmpty(message = "openid必填") 18 private String openid; 19 20 @NotEmpty(message = "购物车不为空") 21 private String items; 22 }
返回的data参数可以看作一个Map<String,String>集合。
2.开发repository层(dao层)
数据库中与订单有关的表有如下两张:
先在repository包下的OrderMasterRepository接口下新建一个sava方法用向order_master表保存数据。再在repository包下的OrderDetailRepository接口下新建一个save方法用来向order_detail表保存数据。
1 package club.nipengfei.sell1.repository; 2 3 import club.nipengfei.sell1.dataobject.OrderMaster; 4 import org.apache.ibatis.annotations.Insert; 5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Select; 7 import org.apache.ibatis.annotations.Update; 8 import org.springframework.stereotype.Repository; 9 10 import java.util.List; 11 12 @Repository 13 @Mapper 14 public interface OrderMasterRepository { 15 16 @Select("select * from order_master where buyer_openid=#{buyerOpenid}") 17 List<OrderMaster> findByBuyerOpenid(String buyerOpenid); 18 19 @Insert("insert into order_master (order_id,buyer_name,buyer_phone,buyer_address,buyer_openid,order_amount,order_status,pay_status) values(#{order_id},#{buyer_name},#{buyer_phone},#{buyer_address},#{buyer_openid},#{order_amount},#{order_status},#{pay_status})") 20 void save(OrderMaster orderMaster); 21 22 @Select("select * from order_master where order_id=#{order_id}") 23 OrderMaster findOne(String order_id); 24 25 @Update("update order_master set order_status=#{order_status} where order_id=#{order_id}") 26 void updateOrderMasterStatus(OrderMaster orderMaster); 27 28 @Update("update order_master set pay_status=#{pay_status} where order_id=#{order_id}") 29 void updateOrderMasterPayStatus(OrderMaster orderMaster); 30 }
1 package club.nipengfei.sell1.repository; 2 3 import club.nipengfei.sell1.dataobject.OrderDetail; 4 import org.apache.ibatis.annotations.Insert; 5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Select; 7 import org.springframework.stereotype.Repository; 8 9 import java.util.List; 10 11 @Repository 12 @Mapper 13 public interface OrderDetailRepository { 14 15 @Select("select * from order_detail where order_id=#{orderId}") 16 List<OrderDetail> findByOrderId(String orderId); 17 18 @Insert("insert into order_detail (detail_id,order_id,product_id,product_name,product_price,product_quantity,product_icon) values(#{detail_id},#{order_id},#{product_id},#{product_name},#{product_price},#{product_quantity},#{product_icon})") 19 void save(OrderDetail orderDetail); 20 }
显然根据OrderFrom类中的数据是不充分的,比如没有order_amount订单总价字段信息等 。因此在service层需要计算相应的总价,这部分在service再写。
在order_detail表中有product_name、product_icon等字段,这些信息需要根据前端的productId查询完整的产品信息在保存到order_detail表中。
3.开发controller层
新建一个OrderDTO类,用来封装根据OrderForm前端传入的表单数查询出更加详细的信息。使用Gson将orderForm中的字符串转为List<OrderDetail>
1 package club.nipengfei.sell1.dto; 2 3 import club.nipengfei.sell1.dataobject.OrderDetail; 4 import club.nipengfei.sell1.utils.serializer.Date2LongSerializer; 5 import com.fasterxml.jackson.annotation.JsonInclude; 6 import com.fasterxml.jackson.annotation.JsonProperty; 7 import com.fasterxml.jackson.databind.annotation.JsonSerialize; 8 import lombok.Data; 9 10 import java.math.BigDecimal; 11 import java.util.Date; 12 import java.util.List; 13 14 @Data 15 // @JsonInclude(JsonInclude.Include.NON_NULL) // 当为null值时不返回该字段 16 public class OrderDTO { 17 18 @JsonProperty("orderId") 19 private String order_id; 20 21 @JsonProperty("buyerName") 22 private String buyer_name; 23 24 @JsonProperty("buyerPhone") 25 private String buyer_phone; 26 27 @JsonProperty("buyerAddress") 28 private String buyer_address; 29 30 @JsonProperty("buyerOpenid") 31 private String buyer_openid; 32 33 @JsonProperty("orderAmount") 34 private BigDecimal order_amount; 35 36 /** 订单状态 默认0新订单 */ 37 @JsonProperty("orderStatus") 38 private Integer order_status; 39 40 /** 支付状态 默认0等待支付 */ 41 @JsonProperty("payStatus") 42 private Integer pay_status; 43 44 @JsonProperty("createTime") 45 @JsonSerialize(using = Date2LongSerializer.class) 46 private Date create_time; 47 48 @JsonProperty("updateTime") 49 @JsonSerialize(using = Date2LongSerializer.class) 50 private Date update_time; 51 52 List<OrderDetail> orderDetailList; 53 }
1 package club.nipengfei.sell1.converter; 2 3 import club.nipengfei.sell1.dataobject.OrderDetail; 4 import club.nipengfei.sell1.dataobject.OrderDetail1; 5 import club.nipengfei.sell1.dto.OrderDTO; 6 import club.nipengfei.sell1.enums.ResultEnum; 7 import club.nipengfei.sell1.exception.SellException; 8 import club.nipengfei.sell1.form.OrderForm; 9 import com.google.gson.Gson; 10 import com.google.gson.reflect.TypeToken; 11 import lombok.extern.slf4j.Slf4j; 12 13 import java.util.ArrayList; 14 import java.util.List; 15 16 @Slf4j 17 public class OrderForm2OrderDTOConverter { 18 19 public static OrderDTO convert(OrderForm orderForm){ 20 Gson gson = new Gson(); 21 OrderDTO orderDTO = new OrderDTO(); 22 orderDTO.setBuyer_name(orderForm.getName()); 23 orderDTO.setBuyer_phone(orderForm.getPhone()); 24 orderDTO.setBuyer_address(orderForm.getAddress()); 25 orderDTO.setBuyer_openid(orderForm.getOpenid()); 26 27 List<OrderDetail1> orderDetailList1 = new ArrayList<>(); 28 List<OrderDetail> orderDetailList = new ArrayList<>(); 29 30 try { 31 orderDetailList1 = gson.fromJson(orderForm.getItems(),new TypeToken<List<OrderDetail1>>(){}.getType()); 32 for (OrderDetail1 orderDetail1 : orderDetailList1) { 33 OrderDetail o1 = new OrderDetail(); 34 o1.setProduct_id(orderDetail1.getProductId()); 35 o1.setProduct_quantity(orderDetail1.getProductQuantity()); 36 orderDetailList.add(o1); 37 } 38 39 }catch (Exception e){ 40 log.error("【对象转换】错误,String={}",orderForm.getItems()); 41 throw new SellException(ResultEnum.PARAM_ERROR); 42 } 43 orderDTO.setOrderDetailList(orderDetailList); 44 45 return orderDTO; 46 47 } 48 }
1 package club.nipengfei.sell1.controller; 2 3 import club.nipengfei.sell1.VO.ResultVO; 4 import club.nipengfei.sell1.converter.OrderForm2OrderDTOConverter; 5 import club.nipengfei.sell1.dto.OrderDTO; 6 import club.nipengfei.sell1.enums.ResultEnum; 7 import club.nipengfei.sell1.exception.SellException; 8 import club.nipengfei.sell1.form.OrderForm; 9 import club.nipengfei.sell1.service.BuyerService; 10 import club.nipengfei.sell1.service.OrderService; 11 import club.nipengfei.sell1.utils.ResultVOUtil; 12 import com.github.pagehelper.PageInfo; 13 import lombok.extern.slf4j.Slf4j; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.util.CollectionUtils; 16 import org.springframework.util.ResourceUtils; 17 import org.springframework.util.StringUtils; 18 import org.springframework.validation.BindingResult; 19 import org.springframework.web.bind.annotation.*; 20 21 import javax.validation.Valid; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 @RestController 27 @RequestMapping("/buyer/order") 28 @Slf4j 29 public class BuyerOrderController { 30 31 @Autowired 32 private OrderService orderService; 33 34 @Autowired 35 private BuyerService buyerService; 36 37 // 创建订单 38 @PostMapping("/create") 39 public ResultVO<Map<String,String>> create(@Valid OrderForm orderForm, BindingResult bindingResult){ 40 41 if(bindingResult.hasErrors()){ 42 log.error("【创建订单】参数不正确,orderForm={}",orderForm); 43 throw new SellException(ResultEnum.PARAM_ERROR.getCode(),bindingResult.getFieldError().getDefaultMessage()); 44 } 45 46 OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm); 47 48 if(CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){ 49 log.error("【创建订单】购物车为空"); 50 throw new SellException(ResultEnum.CART_EMPTY); 51 } 52 53 OrderDTO createResult = orderService.create(orderDTO); 54 55 Map<String,String> map = new HashMap<>(); 56 map.put("orderId",createResult.getOrder_id()); 57 58 return ResultVOUtil.success(map); 59 } 60 }
根据API文档返回给前端的数据主体数据只有orderId。
4.开发service层
- 查询商品的数量
- 计算出订单总价
- 将订单数据写入orderMaster和orderDetail表中
- 扣库存
1 package club.nipengfei.sell1.service.impl; 2 3 import club.nipengfei.sell1.converter.OrderMaster2OrderDTOConverter; 4 import club.nipengfei.sell1.dataobject.OrderDetail; 5 import club.nipengfei.sell1.dataobject.OrderMaster; 6 import club.nipengfei.sell1.dataobject.ProductInfo; 7 import club.nipengfei.sell1.dto.CartDTO; 8 import club.nipengfei.sell1.dto.OrderDTO; 9 import club.nipengfei.sell1.enums.OrderStatusEnum; 10 import club.nipengfei.sell1.enums.PayStatusEnum; 11 import club.nipengfei.sell1.enums.ResultEnum; 12 import club.nipengfei.sell1.exception.SellException; 13 import club.nipengfei.sell1.repository.OrderDetailRepository; 14 import club.nipengfei.sell1.repository.OrderMasterRepository; 15 import club.nipengfei.sell1.service.OrderService; 16 import club.nipengfei.sell1.service.ProductService; 17 import club.nipengfei.sell1.utils.KeyUtil; 18 import com.github.pagehelper.PageHelper; 19 import lombok.extern.slf4j.Slf4j; 20 import org.springframework.beans.BeanUtils; 21 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.stereotype.Service; 23 import org.springframework.transaction.annotation.Transactional; 24 import org.springframework.util.CollectionUtils; 25 26 import java.math.BigDecimal; 27 import java.math.BigInteger; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.stream.Collector; 31 import java.util.stream.Collectors; 32 33 @Service 34 @Slf4j 35 public class OrderServiceImpl implements OrderService{ 36 37 @Autowired 38 private ProductService productService; 39 40 @Autowired 41 private OrderDetailRepository orderDetailRepository; 42 43 @Autowired 44 private OrderMasterRepository orderMasterRepository; 45 46 @Override 47 @Transactional 48 public OrderDTO create(OrderDTO orderDTO) { 49 50 String orderId = KeyUtil.genUniqueKey(); 51 BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO); 52 List<CartDTO> cartDTOList = new ArrayList<>(); 53 54 // 1.查询商品数量 55 for (OrderDetail orderDetail : orderDTO.getOrderDetailList()) { 56 ProductInfo productInfo = productService.findOne(orderDetail.getProduct_id()); 57 if(productInfo==null){ 58 throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 59 } 60 // 2.计算订单总价 61 orderAmount = productInfo.getProduct_price().multiply(new BigDecimal(orderDetail.getProduct_quantity())).add(orderAmount); 62 // 订单详情入库 63 orderDetail.setDetail_id(KeyUtil.genUniqueKey()); 64 orderDetail.setOrder_id(orderId); 65 BeanUtils.copyProperties(productInfo,orderDetail); 66 orderDetailRepository.save(orderDetail); 67 68 CartDTO cartDTO = new CartDTO(orderDetail.getProduct_id(),orderDetail.getProduct_quantity()); 69 70 cartDTOList.add(cartDTO); 71 72 } 73 // 3.写入订单数据库(orderMaster和orderDetail) 74 OrderMaster orderMaster = new OrderMaster(); 75 // 注意需要先拷贝,防止null值覆盖 76 orderDTO.setOrder_id(orderId); 77 BeanUtils.copyProperties(orderDTO,orderMaster); 78 orderMaster.setOrder_amount(orderAmount); 79 orderMaster.setOrder_status(OrderStatusEnum.NEW.getCode()); 80 orderMaster.setPay_status(PayStatusEnum.WAIT.getCode()); 81 82 orderMasterRepository.save(orderMaster); 83 84 // 4.扣库存 85 productService.decreaseStock(cartDTOList); 86 87 return orderDTO; 88 } 89 }
该service方法主要是将数据完整的写入到两张订单表中,注意需要扣库存,防止相应产品的数量不够。
二、查看订单列表
1.查看API文档
###订单列表
```
GET /sell/buyer/order/list
```
参数
```
openid: 18eu2jwk2kse3r42e2e
page: 1 //从第1页开始
size: 10
```
返回
```
{
"code": 0,
"msg": "成功",
"data": [
{
"orderId": "161873371171128075",
"buyerName": "张三",
"buyerPhone": "18868877111",
"buyerAddress": "慕课网总部",
"buyerOpenid": "18eu2jwk2kse3r42e2e",
"orderAmount": 0,
"orderStatus": 0,
"payStatus": 0,
"createTime": 1490171219,
"updateTime": 1490171219,
"orderDetailList": null
},
{
"orderId": "161873371171128076",
"buyerName": "张三",
"buyerPhone": "18868877111",
"buyerAddress": "慕课网总部",
"buyerOpenid": "18eu2jwk2kse3r42e2e",
"orderAmount": 0,
"orderStatus": 0,
"payStatus": 0,
"createTime": 1490171219,
"updateTime": 1490171219,
"orderDetailList": null
}]
}
```
根据API文档可以知道前端发送的请求是GET请求,请求路径是 /sell/buyer/order/list
传入的参数有page,size表示需要进行分页操作,这里使用mybatis的分页插件PageHelper。
返回的data数据是List<OrderDTO>
2.开发repository层
根据openid从order_Master表中查询出相应信息
1 package club.nipengfei.sell1.repository; 2 3 import club.nipengfei.sell1.dataobject.OrderMaster; 4 import org.apache.ibatis.annotations.Insert; 5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Select; 7 import org.apache.ibatis.annotations.Update; 8 import org.springframework.stereotype.Repository; 9 10 import java.util.List; 11 12 @Repository 13 @Mapper 14 public interface OrderMasterRepository { 15 16 @Select("select * from order_master where buyer_openid=#{buyerOpenid}") 17 List<OrderMaster> findByBuyerOpenid(String buyerOpenid); 18 19 }
3.开发service层
由于使用了分页插件需要引入坐标:
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency>
在调用repository方法之前使用PageHelper.startPage(page,size);会在执行的sql语句后面加上limit语句
1 package club.nipengfei.sell1.service.impl; 2 3 import club.nipengfei.sell1.converter.OrderMaster2OrderDTOConverter; 4 import club.nipengfei.sell1.dataobject.OrderDetail; 5 import club.nipengfei.sell1.dataobject.OrderMaster; 6 import club.nipengfei.sell1.dataobject.ProductInfo; 7 import club.nipengfei.sell1.dto.CartDTO; 8 import club.nipengfei.sell1.dto.OrderDTO; 9 import club.nipengfei.sell1.enums.OrderStatusEnum; 10 import club.nipengfei.sell1.enums.PayStatusEnum; 11 import club.nipengfei.sell1.enums.ResultEnum; 12 import club.nipengfei.sell1.exception.SellException; 13 import club.nipengfei.sell1.repository.OrderDetailRepository; 14 import club.nipengfei.sell1.repository.OrderMasterRepository; 15 import club.nipengfei.sell1.service.OrderService; 16 import club.nipengfei.sell1.service.ProductService; 17 import club.nipengfei.sell1.utils.KeyUtil; 18 import com.github.pagehelper.PageHelper; 19 import lombok.extern.slf4j.Slf4j; 20 import org.springframework.beans.BeanUtils; 21 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.stereotype.Service; 23 import org.springframework.transaction.annotation.Transactional; 24 import org.springframework.util.CollectionUtils; 25 26 import java.math.BigDecimal; 27 import java.math.BigInteger; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.stream.Collector; 31 import java.util.stream.Collectors; 32 33 @Service 34 @Slf4j 35 public class OrderServiceImpl implements OrderService{ 36 37 @Autowired 38 private ProductService productService; 39 40 @Autowired 41 private OrderDetailRepository orderDetailRepository; 42 43 @Autowired 44 private OrderMasterRepository orderMasterRepository; 45 46 @Override 47 public List<OrderDTO> findList(String buyerOpenid, int page, int size) { 48 PageHelper.startPage(page,size); 49 List<OrderMaster> orderMasterList = orderMasterRepository.findByBuyerOpenid(buyerOpenid); 50 List<OrderDTO> orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterList); 51 return orderDTOList; 52 } 53 54 }
4.开发controller层
1 package club.nipengfei.sell1.controller; 2 3 import club.nipengfei.sell1.VO.ResultVO; 4 import club.nipengfei.sell1.converter.OrderForm2OrderDTOConverter; 5 import club.nipengfei.sell1.dto.OrderDTO; 6 import club.nipengfei.sell1.enums.ResultEnum; 7 import club.nipengfei.sell1.exception.SellException; 8 import club.nipengfei.sell1.form.OrderForm; 9 import club.nipengfei.sell1.service.BuyerService; 10 import club.nipengfei.sell1.service.OrderService; 11 import club.nipengfei.sell1.utils.ResultVOUtil; 12 import com.github.pagehelper.PageInfo; 13 import lombok.extern.slf4j.Slf4j; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.util.CollectionUtils; 16 import org.springframework.util.ResourceUtils; 17 import org.springframework.util.StringUtils; 18 import org.springframework.validation.BindingResult; 19 import org.springframework.web.bind.annotation.*; 20 21 import javax.validation.Valid; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 @RestController 27 @RequestMapping("/buyer/order") 28 @Slf4j 29 public class BuyerOrderController { 30 31 @Autowired 32 private OrderService orderService; 33 34 @Autowired 35 private BuyerService buyerService; 36 37 // 订单列表 38 @GetMapping("/list") 39 public ResultVO<List<OrderDTO>> list(@RequestParam("openid") String openid,@RequestParam(value = "page",defaultValue = "1") Integer page,@RequestParam(value = "size",defaultValue = "10") Integer size){ 40 if(StringUtils.isEmpty(openid)){ 41 log.error("【查询订单列表】openid为空"); 42 throw new SellException(ResultEnum.PARAM_ERROR); 43 } 44 45 List<OrderDTO> list = orderService.findList(openid, page, size); 46 // PageInfo pageInfo = new PageInfo(list); 47 return ResultVOUtil.success(list); 48 49 } 50 51 }
三、查看订单详情
1.查看API文档
###查询订单详情
```
GET /sell/buyer/order/detail
```
参数
```
openid: 18eu2jwk2kse3r42e2e
orderId: 161899085773669363
```
返回
```
{
"code": 0,
"msg": "成功",
"data": {
"orderId": "161899085773669363",
"buyerName": "李四",
"buyerPhone": "18868877111",
"buyerAddress": "慕课网总部",
"buyerOpenid": "18eu2jwk2kse3r42e2e",
"orderAmount": 18,
"orderStatus": 0,
"payStatus": 0,
"createTime": 1490177352,
"updateTime": 1490177352,
"orderDetailList": [
{
"detailId": "161899085974995851",
"orderId": "161899085773669363",
"productId": "157875196362360019",
"productName": "招牌奶茶",
"productPrice": 9,
"productQuantity": 2,
"productIcon": "http://xxx.com",
"productImage": "http://xxx.com"
}
]
}
}
```
根据API文档可以知道前端发送的请求是GET请求,请求路径是 /sell/buyer/order/detail
传入的参数有openid和orderId。查看订单详情需要openid是为了安全性,只有当根据orderId查出的openid与传入的参数的openid一致时才能查看。
返回参数data是OrderDTO
2.开发repository层
1 package club.nipengfei.sell1.controller; 2 3 import club.nipengfei.sell1.VO.ResultVO; 4 import club.nipengfei.sell1.converter.OrderForm2OrderDTOConverter; 5 import club.nipengfei.sell1.dto.OrderDTO; 6 import club.nipengfei.sell1.enums.ResultEnum; 7 import club.nipengfei.sell1.exception.SellException; 8 import club.nipengfei.sell1.form.OrderForm; 9 import club.nipengfei.sell1.service.BuyerService; 10 import club.nipengfei.sell1.service.OrderService; 11 import club.nipengfei.sell1.utils.ResultVOUtil; 12 import com.github.pagehelper.PageInfo; 13 import lombok.extern.slf4j.Slf4j; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.util.CollectionUtils; 16 import org.springframework.util.ResourceUtils; 17 import org.springframework.util.StringUtils; 18 import org.springframework.validation.BindingResult; 19 import org.springframework.web.bind.annotation.*; 20 21 import javax.validation.Valid; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 @RestController 27 @RequestMapping("/buyer/order") 28 @Slf4j 29 public class BuyerOrderController { 30 31 @Autowired 32 private OrderService orderService; 33 34 @Autowired 35 private BuyerService buyerService; 36 37 // 订单详情 38 @GetMapping("/detail") 39 public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,@RequestParam("orderId") String orderId){ 40 41 OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId); 42 43 return ResultVOUtil.success(orderDTO); 44 } 45 }
3.开发service层
1 package club.nipengfei.sell1.service.impl; 2 3 import club.nipengfei.sell1.dto.OrderDTO; 4 import club.nipengfei.sell1.enums.ResultEnum; 5 import club.nipengfei.sell1.exception.SellException; 6 import club.nipengfei.sell1.service.BuyerService; 7 import club.nipengfei.sell1.service.OrderService; 8 import lombok.extern.slf4j.Slf4j; 9 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.stereotype.Service; 11 12 @Service 13 @Slf4j 14 public class BuyerServiceImpl implements BuyerService { 15 16 @Autowired 17 private OrderService orderService; 18 19 @Override 20 public OrderDTO findOrderOne(String openid, String orderId) { 21 22 return checkOrderOwner(openid,orderId); 23 } 24 25 @Override 26 public OrderDTO cancelOrder(String openid, String orderId) { 27 OrderDTO orderDTO = checkOrderOwner(openid,orderId); 28 if(orderDTO==null){ 29 log.error("【取消订单】查不到该订单orderId={}",orderId); 30 throw new SellException(ResultEnum.ORDER_NOT_EXIST); 31 } 32 return orderService.cancel(orderDTO); 33 } 34 35 private OrderDTO checkOrderOwner(String openid, String orderId){ 36 OrderDTO orderDTO = orderService.findOne(orderId); 37 if(orderDTO==null) return null; 38 // 判断是否是自己的订单 39 if (!orderDTO.getBuyer_openid().equalsIgnoreCase(openid)){ 40 log.error("【查询订单】订单的openid不一致,openid={},orderDTO={}",openid,orderDTO); 41 throw new SellException(ResultEnum.ORDER_OWNER_ERROR); 42 } 43 return orderDTO; 44 } 45 }
1 package club.nipengfei.sell1.service.impl; 2 3 import club.nipengfei.sell1.converter.OrderMaster2OrderDTOConverter; 4 import club.nipengfei.sell1.dataobject.OrderDetail; 5 import club.nipengfei.sell1.dataobject.OrderMaster; 6 import club.nipengfei.sell1.dataobject.ProductInfo; 7 import club.nipengfei.sell1.dto.CartDTO; 8 import club.nipengfei.sell1.dto.OrderDTO; 9 import club.nipengfei.sell1.enums.OrderStatusEnum; 10 import club.nipengfei.sell1.enums.PayStatusEnum; 11 import club.nipengfei.sell1.enums.ResultEnum; 12 import club.nipengfei.sell1.exception.SellException; 13 import club.nipengfei.sell1.repository.OrderDetailRepository; 14 import club.nipengfei.sell1.repository.OrderMasterRepository; 15 import club.nipengfei.sell1.service.OrderService; 16 import club.nipengfei.sell1.service.ProductService; 17 import club.nipengfei.sell1.utils.KeyUtil; 18 import com.github.pagehelper.PageHelper; 19 import lombok.extern.slf4j.Slf4j; 20 import org.springframework.beans.BeanUtils; 21 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.stereotype.Service; 23 import org.springframework.transaction.annotation.Transactional; 24 import org.springframework.util.CollectionUtils; 25 26 import java.math.BigDecimal; 27 import java.math.BigInteger; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.stream.Collector; 31 import java.util.stream.Collectors; 32 33 @Service 34 @Slf4j 35 public class OrderServiceImpl implements OrderService{ 36 37 @Autowired 38 private ProductService productService; 39 40 @Autowired 41 private OrderDetailRepository orderDetailRepository; 42 43 @Autowired 44 private OrderMasterRepository orderMasterRepository; 45 46 @Override 47 @Transactional 48 public OrderDTO create(OrderDTO orderDTO) { 49 50 String orderId = KeyUtil.genUniqueKey(); 51 BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO); 52 List<CartDTO> cartDTOList = new ArrayList<>(); 53 54 // 1.查询商品数量 55 for (OrderDetail orderDetail : orderDTO.getOrderDetailList()) { 56 ProductInfo productInfo = productService.findOne(orderDetail.getProduct_id()); 57 if(productInfo==null){ 58 throw new SellException(ResultEnum.PRODUCT_NOT_EXIT); 59 } 60 // 2.计算订单总价 61 orderAmount = productInfo.getProduct_price().multiply(new BigDecimal(orderDetail.getProduct_quantity())).add(orderAmount); 62 // 订单详情入库 63 orderDetail.setDetail_id(KeyUtil.genUniqueKey()); 64 orderDetail.setOrder_id(orderId); 65 BeanUtils.copyProperties(productInfo,orderDetail); 66 orderDetailRepository.save(orderDetail); 67 68 CartDTO cartDTO = new CartDTO(orderDetail.getProduct_id(),orderDetail.getProduct_quantity()); 69 70 cartDTOList.add(cartDTO); 71 72 } 73 // 3.写入订单数据库(orderMaster和orderDetail) 74 OrderMaster orderMaster = new OrderMaster(); 75 // 注意需要先拷贝,防止null值覆盖 76 orderDTO.setOrder_id(orderId); 77 BeanUtils.copyProperties(orderDTO,orderMaster); 78 orderMaster.setOrder_amount(orderAmount); 79 orderMaster.setOrder_status(OrderStatusEnum.NEW.getCode()); 80 orderMaster.setPay_status(PayStatusEnum.WAIT.getCode()); 81 82 orderMasterRepository.save(orderMaster); 83 84 // 4.扣库存 85 productService.decreaseStock(cartDTOList); 86 87 return orderDTO; 88 } 89 90 @Override 91 public OrderDTO findOne(String orderId) { 92 93 OrderMaster orderMaster = orderMasterRepository.findOne(orderId); 94 if(orderMaster==null){ 95 throw new SellException(ResultEnum.ORDER_NOT_EXIST); 96 } 97 List<OrderDetail> orderDetailList = orderDetailRepository.findByOrderId(orderId); 98 if(CollectionUtils.isEmpty(orderDetailList)){ 99 throw new SellException(ResultEnum.ORDERDETAIL_NOT_EXIST); 100 } 101 OrderDTO orderDTO = new OrderDTO(); 102 BeanUtils.copyProperties(orderMaster,orderDTO); 103 orderDTO.setOrderDetailList(orderDetailList); 104 return orderDTO; 105 } 106 107 @Override 108 public List<OrderDTO> findList(String buyerOpenid, int page, int size) { 109 PageHelper.startPage(page,size); 110 List<OrderMaster> orderMasterList = orderMasterRepository.findByBuyerOpenid(buyerOpenid); 111 List<OrderDTO> orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterList); 112 return orderDTOList; 113 } 114 115 @Override 116 @Transactional 117 public OrderDTO cancel(OrderDTO orderDTO) { 118 119 OrderMaster orderMaster = new OrderMaster(); 120 121 122 // 判断订单状态 123 if(!orderDTO.getOrder_status().equals(OrderStatusEnum.NEW.getCode())){ 124 log.error("【取消订单】订单状态不正确,orderId={},orderStatus={}",orderDTO.getOrder_id(),orderDTO.getOrder_status()); 125 throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 126 } 127 128 // 修改订单状态 129 orderDTO.setOrder_status(OrderStatusEnum.CANCEL.getCode()); 130 BeanUtils.copyProperties(orderDTO,orderMaster); 131 orderMasterRepository.updateOrderMasterStatus(orderMaster); 132 OrderMaster one = orderMasterRepository.findOne(orderMaster.getOrder_id()); 133 if(one==null||one.getOrder_status()!=2){ 134 log.error("【取消订单】更新失败,orderMaster={}",one); 135 throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 136 } 137 138 // 返还库存 139 if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){ 140 log.error("【取消订单】订单中无商品,orderDTO={}",orderDTO); 141 throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY); 142 } 143 List<CartDTO> cartDTOList = orderDTO.getOrderDetailList().stream().map(e -> new CartDTO(e.getProduct_id(),e.getProduct_quantity())).collect(Collectors.toList()); 144 productService.increaseStock(cartDTOList); 145 // 如果已支付需要退款 146 if (orderDTO.getPay_status().equals(PayStatusEnum.SUCCESS.getCode())){ 147 // TODO 148 } 149 return orderDTO; 150 } 151 152 @Override 153 @Transactional 154 public OrderDTO finish(OrderDTO orderDTO) { 155 // 判断订单状态 156 if (!orderDTO.getOrder_status().equals(OrderStatusEnum.NEW.getCode())){ 157 log.error("【完结订单】订单状态不正确,orderId={},orderStatus={}",orderDTO.getOrder_id(),orderDTO.getOrder_status()); 158 throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 159 } 160 161 // 修改订单状态 162 orderDTO.setOrder_status(OrderStatusEnum.FINISHED.getCode()); 163 OrderMaster orderMaster = new OrderMaster(); 164 BeanUtils.copyProperties(orderDTO,orderMaster); 165 orderMasterRepository.updateOrderMasterStatus(orderMaster); 166 OrderMaster one = orderMasterRepository.findOne(orderMaster.getOrder_id()); 167 if(one==null||one.getOrder_status()!=1){ 168 log.error("【完结订单】更新失败,orderMaster={}",one); 169 throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 170 } 171 172 return orderDTO; 173 } 174 175 @Override 176 @Transactional 177 public OrderDTO paid(OrderDTO orderDTO) { 178 // 判断订单状态 179 if (!orderDTO.getPay_status().equals(PayStatusEnum.WAIT.getCode())){ 180 log.error("【完结订单】订单状态不正确,orderId={},orderPayStatus={}",orderDTO.getOrder_id(),orderDTO.getPay_status()); 181 throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 182 } 183 184 // 判断支付状态 185 if (!orderDTO.getPay_status().equals(PayStatusEnum.WAIT.getCode())){ 186 log.error("【订单支付完成】订单支付状态不正确,orderDTO={}",orderDTO); 187 throw new SellException(ResultEnum.ORDER_PAY_STATUS_ERROR); 188 } 189 190 // 修改支付状态 191 orderDTO.setPay_status(PayStatusEnum.SUCCESS.getCode()); 192 OrderMaster orderMaster = new OrderMaster(); 193 BeanUtils.copyProperties(orderDTO,orderMaster); 194 orderMasterRepository.updateOrderMasterPayStatus(orderMaster); 195 OrderMaster one = orderMasterRepository.findOne(orderMaster.getOrder_id()); 196 if(one==null||one.getPay_status()!=1){ 197 log.error("【订单支付完成】更新失败,orderMaster={}",one); 198 throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 199 } 200 201 return orderDTO; 202 } 203 }
4.开发controller
1 package club.nipengfei.sell1.controller; 2 3 import club.nipengfei.sell1.VO.ResultVO; 4 import club.nipengfei.sell1.converter.OrderForm2OrderDTOConverter; 5 import club.nipengfei.sell1.dto.OrderDTO; 6 import club.nipengfei.sell1.enums.ResultEnum; 7 import club.nipengfei.sell1.exception.SellException; 8 import club.nipengfei.sell1.form.OrderForm; 9 import club.nipengfei.sell1.service.BuyerService; 10 import club.nipengfei.sell1.service.OrderService; 11 import club.nipengfei.sell1.utils.ResultVOUtil; 12 import com.github.pagehelper.PageInfo; 13 import lombok.extern.slf4j.Slf4j; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.util.CollectionUtils; 16 import org.springframework.util.ResourceUtils; 17 import org.springframework.util.StringUtils; 18 import org.springframework.validation.BindingResult; 19 import org.springframework.web.bind.annotation.*; 20 21 import javax.validation.Valid; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 @RestController 27 @RequestMapping("/buyer/order") 28 @Slf4j 29 public class BuyerOrderController { 30 31 @Autowired 32 private OrderService orderService; 33 34 @Autowired 35 private BuyerService buyerService; 36 37 // 订单详情 38 @GetMapping("/detail") 39 public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,@RequestParam("orderId") String orderId){ 40 41 OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId); 42 43 return ResultVOUtil.success(orderDTO); 44 } 45 46 }
四、取消订单
1.查看API文档
###取消订单
```
POST /sell/buyer/order/cancel
```
参数
```
openid: 18eu2jwk2kse3r42e2e
orderId: 161899085773669363
```
返回
```
{
"code": 0,
"msg": "成功",
"data": null
}
```
根据API文档可以知道前端发送的请求是POST请求,请求路径是 /sell/buyer/order/cancel
传入的参数有openid和orderId。
2.开发controller层
1 package club.nipengfei.sell1.controller; 2 3 import club.nipengfei.sell1.VO.ResultVO; 4 import club.nipengfei.sell1.converter.OrderForm2OrderDTOConverter; 5 import club.nipengfei.sell1.dto.OrderDTO; 6 import club.nipengfei.sell1.enums.ResultEnum; 7 import club.nipengfei.sell1.exception.SellException; 8 import club.nipengfei.sell1.form.OrderForm; 9 import club.nipengfei.sell1.service.BuyerService; 10 import club.nipengfei.sell1.service.OrderService; 11 import club.nipengfei.sell1.utils.ResultVOUtil; 12 import com.github.pagehelper.PageInfo; 13 import lombok.extern.slf4j.Slf4j; 14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.util.CollectionUtils; 16 import org.springframework.util.ResourceUtils; 17 import org.springframework.util.StringUtils; 18 import org.springframework.validation.BindingResult; 19 import org.springframework.web.bind.annotation.*; 20 21 import javax.validation.Valid; 22 import java.util.HashMap; 23 import java.util.List; 24 import java.util.Map; 25 26 @RestController 27 @RequestMapping("/buyer/order") 28 @Slf4j 29 public class BuyerOrderController { 30 31 @Autowired 32 private OrderService orderService; 33 34 @Autowired 35 private BuyerService buyerService; 36 37 // 取消订单 38 @PostMapping("/cancel") 39 public ResultVO cancel(@RequestParam("openid") String openid,@RequestParam("orderId") String orderId){ 40 buyerService.cancelOrder(openid, orderId); 41 return ResultVOUtil.success(); 42 } 43 }
3.开发service层
- 判断订单状态,如果订单不是新建的,那么就抛出异常,提示订单状态不正确
- 修改订单状态至取消
- 返还库存
1 package club.nipengfei.sell1.service.impl; 2 3 import club.nipengfei.sell1.converter.OrderMaster2OrderDTOConverter; 4 import club.nipengfei.sell1.dataobject.OrderDetail; 5 import club.nipengfei.sell1.dataobject.OrderMaster; 6 import club.nipengfei.sell1.dataobject.ProductInfo; 7 import club.nipengfei.sell1.dto.CartDTO; 8 import club.nipengfei.sell1.dto.OrderDTO; 9 import club.nipengfei.sell1.enums.OrderStatusEnum; 10 import club.nipengfei.sell1.enums.PayStatusEnum; 11 import club.nipengfei.sell1.enums.ResultEnum; 12 import club.nipengfei.sell1.exception.SellException; 13 import club.nipengfei.sell1.repository.OrderDetailRepository; 14 import club.nipengfei.sell1.repository.OrderMasterRepository; 15 import club.nipengfei.sell1.service.OrderService; 16 import club.nipengfei.sell1.service.ProductService; 17 import club.nipengfei.sell1.utils.KeyUtil; 18 import com.github.pagehelper.PageHelper; 19 import lombok.extern.slf4j.Slf4j; 20 import org.springframework.beans.BeanUtils; 21 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.stereotype.Service; 23 import org.springframework.transaction.annotation.Transactional; 24 import org.springframework.util.CollectionUtils; 25 26 import java.math.BigDecimal; 27 import java.math.BigInteger; 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.stream.Collector; 31 import java.util.stream.Collectors; 32 33 @Service 34 @Slf4j 35 public class OrderServiceImpl implements OrderService{ 36 37 @Autowired 38 private ProductService productService; 39 40 @Autowired 41 private OrderDetailRepository orderDetailRepository; 42 43 @Autowired 44 private OrderMasterRepository orderMasterRepository; 45 46 @Override 47 @Transactional 48 public OrderDTO cancel(OrderDTO orderDTO) { 49 50 OrderMaster orderMaster = new OrderMaster(); 51 52 53 // 判断订单状态 54 if(!orderDTO.getOrder_status().equals(OrderStatusEnum.NEW.getCode())){ 55 log.error("【取消订单】订单状态不正确,orderId={},orderStatus={}",orderDTO.getOrder_id(),orderDTO.getOrder_status()); 56 throw new SellException(ResultEnum.ORDER_STATUS_ERROR); 57 } 58 59 // 修改订单状态 60 orderDTO.setOrder_status(OrderStatusEnum.CANCEL.getCode()); 61 BeanUtils.copyProperties(orderDTO,orderMaster); 62 orderMasterRepository.updateOrderMasterStatus(orderMaster); 63 OrderMaster one = orderMasterRepository.findOne(orderMaster.getOrder_id()); 64 if(one==null||one.getOrder_status()!=2){ 65 log.error("【取消订单】更新失败,orderMaster={}",one); 66 throw new SellException(ResultEnum.ORDER_UPDATE_FAIL); 67 } 68 69 // 返还库存 70 if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){ 71 log.error("【取消订单】订单中无商品,orderDTO={}",orderDTO); 72 throw new SellException(ResultEnum.ORDER_DETAIL_EMPTY); 73 } 74 List<CartDTO> cartDTOList = orderDTO.getOrderDetailList().stream().map(e -> new CartDTO(e.getProduct_id(),e.getProduct_quantity())).collect(Collectors.toList()); 75 productService.increaseStock(cartDTOList); 76 // 如果已支付需要退款 77 if (orderDTO.getPay_status().equals(PayStatusEnum.SUCCESS.getCode())){ 78 // TODO 79 } 80 return orderDTO; 81 } 82 83 }
4.开发repository层
1 package club.nipengfei.sell1.repository; 2 3 import club.nipengfei.sell1.dataobject.ProductInfo; 4 import com.github.pagehelper.Page; 5 import org.apache.ibatis.annotations.Insert; 6 import org.apache.ibatis.annotations.Mapper; 7 import org.apache.ibatis.annotations.Select; 8 import org.apache.ibatis.annotations.Update; 9 import org.springframework.stereotype.Repository; 10 11 import java.util.List; 12 13 @Repository 14 @Mapper 15 public interface ProductInfoRepository { 16 17 @Select("select * from product_info where product_status=#{productStatus}") 18 List<ProductInfo> findByProductStatus(Integer productStatus); 19 20 @Insert("insert into product_info(product_id,product_name,product_price,product_stock,product_description,product_icon,product_status,category_type) values(#{product_id},#{product_name},#{product_price},#{product_stock},#{product_description},#{product_icon},#{product_status},#{category_type})") 21 void save(ProductInfo productInfo); 22 23 @Select("select * from product_info where product_id=#{productId}") 24 ProductInfo findOne(String productId); 25 26 @Select("select * from product_info") 27 List<ProductInfo> findAll(); 28 29 @Update("update product_info set product_stock=#{product_stock} where product_id=#{product_id}") 30 void updateProductStock(ProductInfo productInfo); 31 }
1 package club.nipengfei.sell1.repository; 2 3 import club.nipengfei.sell1.dataobject.OrderMaster; 4 import org.apache.ibatis.annotations.Insert; 5 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Select; 7 import org.apache.ibatis.annotations.Update; 8 import org.springframework.stereotype.Repository; 9 10 import java.util.List; 11 12 @Repository 13 @Mapper 14 public interface OrderMasterRepository { 15 16 @Select("select * from order_master where buyer_openid=#{buyerOpenid}") 17 List<OrderMaster> findByBuyerOpenid(String buyerOpenid); 18 19 @Insert("insert into order_master (order_id,buyer_name,buyer_phone,buyer_address,buyer_openid,order_amount,order_status,pay_status) values(#{order_id},#{buyer_name},#{buyer_phone},#{buyer_address},#{buyer_openid},#{order_amount},#{order_status},#{pay_status})") 20 void save(OrderMaster orderMaster); 21 22 @Select("select * from order_master where order_id=#{order_id}") 23 OrderMaster findOne(String order_id); 24 25 @Update("update order_master set order_status=#{order_status} where order_id=#{order_id}") 26 void updateOrderMasterStatus(OrderMaster orderMaster); 27 28 @Update("update order_master set pay_status=#{pay_status} where order_id=#{order_id}") 29 void updateOrderMasterPayStatus(OrderMaster orderMaster); 30 }