分析:1. 返回的是resultvo
2. data里面可以当做返回的是map
3. 对于参数可以创建一个OrderForm,面向前端
4. post请求
第一步:创建订单
1. Controller:BuyerOrderController.java
package com.fjz.vxsell.controller;
import com.fjz.vxsell.converter.OrderFormToOrderDTOConverter;
import com.fjz.vxsell.dto.OrderDTO;
import com.fjz.vxsell.enums.ExceptionEnums;
import com.fjz.vxsell.exception.VxsellException;
import com.fjz.vxsell.form.OrderForm;
import com.fjz.vxsell.service.OrderService;
import com.fjz.vxsell.utils.ResultVoUtils;
import com.fjz.vxsell.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
/**
* 买家订单
* @author 冯师兄
* @date 2020-05-13 14:35
*/
@RestController
@RequestMapping("/buyer/order")
@Slf4j
public class BuyerOrderController {
@Autowired
private OrderService orderService;
/**
* 创建订单
* @param orderForm
* @param bindingResult
* @return
*/
@PostMapping("/create")
public ResultVo<Map<String, String>> create(@Valid OrderForm orderForm, BindingResult bindingResult){
if (bindingResult.hasErrors()){
log.info("【创建订单】参数不正确: orderForm={}", orderForm);
//不止要返回:参数不正确,还要 返回哪些参数不正确
throw new VxsellException(ExceptionEnums.PARAM_ERROR.getCode(),
bindingResult.getFieldError().getDefaultMessage());
}
//因为create方法里面的参数为orderDTO,座椅这里需要将orderForm,转换为orderDTO,这里使用了一个转换器
OrderDTO orderDTO = OrderFormToOrderDTOConverter.convert(orderForm);
//这里还需要判断购物车是否为空
if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){
log.info("【创建订单】购物车为空");
throw new VxsellException(ExceptionEnums.CART_EMPTY);
}
OrderDTO result = orderService.create(orderDTO);
//因为返回类型ResultVo里面是map类型
Map<String, String> map = new HashMap<>();
map.put("orderId", result.getOrderId());
return ResultVoUtils.success(map);
}
//查询订单列表
//查询订单详情
//取消订单
}
2. 编写OrderForm.java
package com.fjz.vxsell.form;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
/**
* 用于展示给前端的参数表单,自己创建的
* @author 冯师兄
* @date 2020-05-13 14:39
*/
@Data
public class OrderForm {
//买家姓名
@NotEmpty(message = "买家姓名不能为空")
private String name;
//买家电话
@NotEmpty(message = "买家电话不能为空")
private String phone;
//买家地址
@NotEmpty(message = "买家地址不能为空")
private String address;
//买家微信openid
@NotEmpty(message = "买家微信openid不能为空")
private String openid;
//购物车
@NotEmpty(message = "购物车不能为空")
private String items;
}
3. 编写OrderFormToOrderDTOConverter.java
package com.fjz.vxsell.converter;
import com.fjz.vxsell.bean.OrderDetail;
import com.fjz.vxsell.dto.OrderDTO;
import com.fjz.vxsell.enums.ExceptionEnums;
import com.fjz.vxsell.exception.VxsellException;
import com.fjz.vxsell.form.OrderForm;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
/**
* @author 冯师兄
* @date 2020-05-13 15:02
*/
@Slf4j
public class OrderFormToOrderDTOConverter {
public static OrderDTO convert(OrderForm orderForm){
Gson gson = new Gson();
OrderDTO orderDTO = new OrderDTO();
/**
* 这里为什么不用beanutils,以为orderDTO与orderForm两边的参数不同,
* 比如:orderDTO为buyerName,而orderForm为name
* 所以不能用beanutils
*
*/
orderDTO.setBuyerName(orderForm.getName());
orderDTO.setBuyerPhone(orderForm.getPhone());
orderDTO.setBuyerAddress(orderForm.getAddress());
orderDTO.setBuyerOpenid(orderForm.getOpenid());
/**
* 这里需要将items转换,items是String类型,但是里面实际上是json
* 需要用到Gson,将json装换为List
*/
List<OrderDetail> orderDetailList = new ArrayList<>();
try {
orderDetailList = gson.fromJson(orderForm.getItems(),
new TypeToken<List<OrderDetail>>(){}.getType());
}catch (Exception e){
log.error("【对象转换】错误:String={}", orderForm.getItems());
throw new VxsellException(ExceptionEnums.PARAM_ERROR);
}
orderDTO.setOrderDetailList(orderDetailList);
return orderDTO;
}
}
4. 在pom.xml中添加Gosn依赖
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
5. ExceptionEnums.java
package com.fjz.vxsell.enums;
import lombok.Getter;
/**
* @author 冯师兄
* @date 2020-05-08 17:46
*/
@Getter
public enum ExceptionEnums {
PRODUCT_NOT_EXSIT(10 ,"商品不存在"),
PRODUCT_STOCK_ERROR(11, "库存不正确"),
ORDER_NOT_EXSIT(12, "订单不存在"),
ORDERDETAIL_NOT_EXSIT(13, "订单详情不存在"),
ORDER_STATUS_ERROR(14, "订单状态不正确"),
ORDER_UPDATE_FAIL(15, "订单更新失败"),
ORDERDETAIL_IS_EMPTY(16, "订单详情为空"),
ORDER_PAY_STATUS_ERROR(17, "订单支付状态不正确"),
PARAM_ERROR(18, "参数不正确"),
CART_EMPTY(19, "购物车为空"),
;
private Integer code;
private String message;
ExceptionEnums(Integer code, String message) {
this.code = code;
this.message = message;
}
}
6. VxsellException.java
package com.fjz.vxsell.exception;
import com.fjz.vxsell.enums.ExceptionEnums;
/**
* @author 冯师兄
* @date 2020-05-08 17:44
*/
public class VxsellException extends RuntimeException {
private Integer code;
public VxsellException(ExceptionEnums exceptionEnums) {
super(exceptionEnums.getMessage());
this.code = exceptionEnums.getCode();
}
public VxsellException(Integer code, String message) {
super(message);
this.code = code;
}
}
7. 测试:显示orderid为空,我这里用的是postman接口测试工具
原来是在OrderServiceImpl中我们已经将orderDTO写入到orderMaster中,orderDTO当然就会没有数据。
解决办法:
OrderServiceImpl.java
/**
* 创建订单
* @param orderDTO
* @return
*/
@Override
@Transactional
public OrderDTO create(OrderDTO orderDTO) {
String orderId = KeyUniqueUtils.genKeyUnique();
BigDecimal orderAmount = new BigDecimal(0);
//1. 查询商品(数据,价格)
List<OrderDetail> orderDetailList = orderDTO.getOrderDetailList();
//List<CartDTO> cartDTOList = new ArrayList<>();
for(OrderDetail orderDetail : orderDetailList){
//根据商品id查询
ProductInfo productInfo = productInfoService.findById(orderDetail.getProductId());
//判断商品是否存在,这里用到了一个异常和枚举
if (productInfo == null){
throw new VxsellException(ExceptionEnums.PRODUCT_NOT_EXSIT);
}
//2. 计算总价格:单个 商品的数量*价格,再加上上一次循环查询到的总价格
orderAmount = productInfo.getProductPrice()
.multiply(new BigDecimal(orderDetail.getProductQuantity()))
.add(orderAmount);
//3. 订单详情入库
//生成随机数,写了一个工具类
orderDetail.setDetailId(KeyUniqueUtils.genKeyUnique());
//订单id是在生成订单的时候就已经生成了
orderDetail.setOrderId(orderId);
//这里还少一些商品名称,图片等
BeanUtils.copyProperties(productInfo, orderDetail);
orderDetailRepository.save(orderDetail);
/* //5. 扣除库存,这样也可以,但是下面5的方法更简单,是角度看1.8的特性
CartDTO cartDTO = new CartDTO(orderDetail.getProductId(), orderDetail.getProductQuantity());
cartDTOList.add(cartDTO);
productService.decreaseStock(cartDTOList);
*/
}
//4. 写入订单数据库
OrderMaster orderMaster = new OrderMaster();
orderDTO.setOrderId(orderId);
BeanUtils.copyProperties(orderDTO, orderMaster);
orderMaster.setOrderAmount(orderAmount);
orderMaster.setOrderStatus(OrderStatusEnums.NEW.getCode());
orderMaster.setPayerStatus(PayStatusEnums.WAIT.getCode());
orderMasterRepository.save(orderMaster);
//5. 扣除库存
List<CartDTO> cartDTOList = orderDetailList.stream()
.map(e -> new CartDTO(e.getProductId(), e.getProductQuantity()))
.collect(Collectors.toList());
productInfoService.decreaseStock(cartDTOList);
return orderDTO;
}