订单模块

功能介绍:

前台功能:

1.创建订单

controller层实现:

传入userId和收货地址shippingId,由后台自动创建订单。

 1     @RequestMapping("create.do")
 2     @ResponseBody
 3     public ServerResponse create(HttpServletRequest request, Integer shippingId) {
 4     //    User user = (User)session.getAttribute(Const.CURRENT_USER);
 5 
 6         String loginToken = CookieUtil.readLoginToken(request);
 7         if(StringUtils.isEmpty(loginToken)) {
 8             return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
 9         }
10         String userJsonStr = RedisShardedPoolUtil.get(loginToken);
11         User user = JsonUtil.string2Obj(userJsonStr, User.class);
12 
13         if(user ==null){
14             return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
15         }
16         //将userId和shippingId传入,创建订单
17         return iOrderService.createOrder(user.getId(), shippingId);
18     }
View Code

service层实现:

1)根据userId从购物车表CART中将已勾选的商品取出来,由cartList保存,然后根据这个cartList,由getCartOrderItem()生成订单详情orderItemList。

2)由订单详情orderItemList可以计算出整个订单的总价,由getOrderTotalPrice()实现。

3)根据以上计算出来的订单总价、收货地址shipingId、userId生成最后的订单order,由assembleOrder()实现,并持久化到数据库中。

4)由assembleOrder()生成的订单,是带有最后的订单号的orderNo,所以将这个订单号更新到之前的订单详情orderItemList中,由mybatis的批量插入实现。

5)根据订单详情orderItemList,去对应的商品表中减库存,由reduceProductStock()实现。

6)清空当前购物车,由cleanCart()实现。

7)将生成的最后的订单order和订单详情orderItemList,组合成vo后返回给前台。

 1     public ServerResponse createOrder(Integer userId, Integer shippingId) {
 2         //从购物车中获取数据
 3         //将购物车中已勾选的物品获取出来,这些物品会用来生成订单
 4         List<Cart> cartList = cartMapper.selectCheckedCartByUserId(userId);
 5 
 6         //根据这些物品,即cartList,生成订单详情List
 7         ServerResponse serverResponse = this.getCartOrderItem(userId, cartList);
 8         if(!serverResponse.isSuccess()) {
 9             return serverResponse;
10         }
11         List<OrderItem> orderItemList = (List<OrderItem>)serverResponse.getData();
12         //根据订单详情list,计算订单总价
13         BigDecimal payment = this.getOrderTotalPrice(orderItemList);
14 
15         //生成订单
16         Order order = this.assembleOrder(userId, shippingId, payment);
17         if(order == null) {
18             return ServerResponse.createByErrorMessage("生成订单错误");
19         }
20         if(CollectionUtils.isEmpty(orderItemList)) {
21             return ServerResponse.createByErrorMessage("购物车为空");
22         }
23         //将订单号逐一的更新到当前订单详情中,也就是一条订单数据可以对应多条订单详情
24         for(OrderItem orderItem : orderItemList) {
25             orderItem.setOrderNo(order.getOrderNo());
26         }
27         //mybatis批量插入
28         //由于订单详情,一次性可能有多个商品,多个订单详情,也就是多条数据,所以这里就要使用一次性批量插入
29         orderItemMapper.batchInsert(orderItemList);
30         //生成成功,减少产品的库存
31         this.reduceProductStock(orderItemList);
32 
33         //清空购物车
34         this.cleanCart(cartList);
35 
36         //将订单明细返回给前端,返回给前端
37         //pojo->vo
38         //组装vo,传给前端的数据
39         OrderVo orderVo = assembleOrderVo(order, orderItemList);
40         return ServerResponse.createBySuccess(orderVo);
41     }
View Code

getCartOrderItem()由购物车勾选状态生成订单详情实现:

从购物车表中获取productId,然后从product表中获取当前商品的详细信息,校验商品的在售和库存状态,然后组装订单详情,一种商品对应一个订单详情,一个订单详情由orderNo唯一标识,多个订单详情对应一个订单,最后将组装完成的订单详情cartItemList返回。

 1     private ServerResponse getCartOrderItem(Integer userId,List<Cart> cartList){
 2         List<OrderItem> orderItemList = Lists.newArrayList();
 3         if(CollectionUtils.isEmpty(cartList)){
 4             return ServerResponse.createByErrorMessage("购物车为空");
 5         }
 6 
 7         //校验购物车的数据,包括产品的状态和数量
 8         for(Cart cartItem : cartList){
 9             OrderItem orderItem = new OrderItem();
10             //从购物车中获取productId,然后从product表中获取当前产品的详细信息
11             Product product = productMapper.selectByPrimaryKey(cartItem.getProductId());
12             //查看当前产品是否在售
13             if(Const.ProductStatusEnum.ON_SALE.getCode() != product.getStatus()){
14                 return ServerResponse.createByErrorMessage("产品"+product.getName()+"不是在线售卖状态");
15             }
16 
17             //校验库存,校验当前产品选购的数量是否超过产品本身库存
18             if(cartItem.getQuantity() > product.getStock()){
19                 return ServerResponse.createByErrorMessage("产品"+product.getName()+"库存不足");
20             }
21 
22             //组装订单详情,一种商品,一个订单详情,而订单详情又由orderNo唯一标识,所以可能多种商品有同样的orderNo,而orderNo又对应订单order中的一个订单,也由orderNo唯一标识
23 
24             orderItem.setUserId(userId);
25             orderItem.setProductId(product.getId());
26             orderItem.setProductName(product.getName());
27             orderItem.setProductImage(product.getMainImage());
28             orderItem.setCurrentUnitPrice(product.getPrice());
29             orderItem.setQuantity(cartItem.getQuantity());
30             // 这里将当前商品的总价:单价*数量,存进数据表
31             orderItem.setTotalPrice(BigDecimalUtil.mul(product.getPrice().doubleValue(),cartItem.getQuantity()));
32             //将当前订单详情加入订单详情List中
33             orderItemList.add(orderItem);
34         }
35         //将订单详情list返回
36         return ServerResponse.createBySuccess(orderItemList);
37     }
View Code

getOrderTotalPrice()由订单详情计算出整个订单的总价:

由于在生成订单详情的时候,已经对每种商品单独计算过对应的总价,存储在订单详情中了,所以这里只需要将订单中的所有商品价值相加即可。

1     private BigDecimal getOrderTotalPrice(List<OrderItem> orderItemList) {
2         BigDecimal payment = new BigDecimal("0");
3         //计算当前订单总计,逐一相加
4         for(OrderItem orderItem : orderItemList) {
5             payment = BigDecimalUtil.add(payment.doubleValue(), orderItem.getTotalPrice().doubleValue());
6         }
7         return payment;
8     }
View Code

assembleOrder()由userId、订单详情、总价组装最后的订单:

由generateOrderNo()生成订单号,然后添加订单所需要的字段,比如订单号、订单状态、运费、支付类型、订单总价等,然后将订单持久化到数据库中。

 1     private Order assembleOrder(Integer userId, Integer shippingId, BigDecimal payment) {
 2         Order order = new Order();
 3         //生成订单号orderNo,很重要
 4         long orderNo = this.generateOrderNo();
 5         //设置订单号
 6         order.setOrderNo(orderNo);
 7         //设置订单状态
 8         order.setStatus(Const.OrderStatusEnum.NO_PAY.getCode());
 9         //设置运费
10         order.setPostage(0);
11         //设置支付类型
12         order.setPaymentType(Const.PaymentTypeEnum.ONLINE_PAY.getCode());
13         //设置订单总价
14         order.setPayment(payment);
15         order.setUserId(userId);
16         order.setShippingId(shippingId);
17 
18         //将这个订单持久化到数据库中
19         int rowCount = orderMapper.insert(order);
20         if(rowCount > 0) {
21             return order;
22         }
23         return null;
24     }
View Code

reduceProductStock()由订单详情去对应的商品表中减库存:

 1     private void reduceProductStock(List<OrderItem> orderItemList) {
 2         //根据订单详情list,逐一针对商品,去product表中减库存
 3         for(OrderItem orderItem : orderItemList) {
 4             //根据productId,从product表中拿到当前商品
 5             Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
 6             //减库存
 7             product.setStock(product.getStock() - orderItem.getQuantity());
 8             //将库存信息更新到product表中
 9             productMapper.updateByPrimaryKeySelective(product);
10         }
11     }
View Code

cleanCart()清空购物车:

1     private void cleanCart(List<Cart> cartList) {
2         for(Cart cart : cartList) {
3             //更新cart购物车表
4             cartMapper.deleteByPrimaryKey(cart.getId());
5         }
6     }
View Code

2.获取购物车中已经选中的商品信息

service层实现:

根据userId从购物车表中,将当前用户选中的商品拿出来,由cartList记录。根据cartList,由getCartOrderItem()得到订单详情orderItemList,从订单详情orderItemList中计算订单总价。最后将订单详情、订单总价等组装成对应的vo对象返回给前端。

 1     public ServerResponse getOrderCartProduct(Integer userId) {
 2         OrderProductVo orderProductVo = new OrderProductVo();
 3         //从购物车中获取数据
 4         //根据userId,从购物车表中,将当前用户选中的商品拿出来
 5         List<Cart> cartList = cartMapper.selectCheckedCartByUserId(userId);
 6         //根据选中的商品list,得到订单详情
 7         ServerResponse serverResponse =  this.getCartOrderItem(userId,cartList);
 8         if(!serverResponse.isSuccess()){
 9             return serverResponse;
10         }
11         List<OrderItem> orderItemList =( List<OrderItem> ) serverResponse.getData();
12 
13         List<OrderItemVo> orderItemVoList = Lists.newArrayList();
14         //从订单详情list中,计算订单总价
15         BigDecimal payment = new BigDecimal("0");
16         for(OrderItem orderItem : orderItemList){
17             //计算订单总价
18             payment = BigDecimalUtil.add(payment.doubleValue(),orderItem.getTotalPrice().doubleValue());
19             //将订单详情,组装成订单详情vo对象,放在voList中
20             orderItemVoList.add(assembleOrderItemVo(orderItem));
21         }
22         //将订单总价放在orderProductVo中
23         orderProductVo.setProductTotalPrice(payment);
24         //将订单详情voList放在orderProductVo中
25         orderProductVo.setOrderItemVoList(orderItemVoList);
26         //将图片服务器地址放在orderProductVo中
27         orderProductVo.setImageHost(PropertiesUtil.getProperty("ftp.server.http.prefix"));
28         //将orderProductVo返回
29         return ServerResponse.createBySuccess(orderProductVo);
30     }
View Code

3.订单列表

4.订单详情

5.取消订单

controller层实现:

传入userId,orderNo参数,通过service层实现:

 1     @RequestMapping("cancel.do")
 2     @ResponseBody
 3     public ServerResponse cancel(HttpServletRequest request , Long orderNo) {
 4     //    User user = (User)session.getAttribute(Const.CURRENT_USER);
 5 
 6         String loginToken = CookieUtil.readLoginToken(request);
 7         if(StringUtils.isEmpty(loginToken)) {
 8             return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
 9         }
10         String userJsonStr = RedisShardedPoolUtil.get(loginToken);
11         User user = JsonUtil.string2Obj(userJsonStr, User.class);
12 
13         if(user ==null){
14             return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(),ResponseCode.NEED_LOGIN.getDesc());
15         }
16         return iOrderService.cancel(user.getId(), orderNo);
17     }
View Code

service层实现:

通过userId,orderNo查到对应的订单,如果订单状态是未付款,则置订单状态为CANCELED,更行到数据库即可。

 1     public ServerResponse<String> cancel(Integer userId, Long orderNo) {
 2         //根据userId和orderNo拿到订单
 3         Order order = orderMapper.selectByUserIdAndOrderNo(userId, orderNo);
 4         if(order == null) {
 5             return ServerResponse.createByErrorMessage("该用户此订单不存在");
 6         }
 7         //判断订单状态
 8         if(order.getStatus() != Const.OrderStatusEnum.NO_PAY.getCode()) {
 9             return ServerResponse.createByErrorMessage("已付款,无法取消订单");
10         }
11         Order updateOrder = new Order();
12         updateOrder.setId(order.getId());
13         //更新订单状态
14         updateOrder.setStatus(Const.OrderStatusEnum.CANCELED.getCode());
15         //将更新状态更新到数据库中
16         int row = orderMapper.updateByPrimaryKeySelective(updateOrder);
17         if(row > 0) {
18             return ServerResponse.createBySuccess();
19         }
20         return ServerResponse.createByError();
21     }
View Code

 

后台功能:

1.订单列表

2.订单搜索

3.订单详情

4.订单发货

 

学习目标:

1.设计实用、安全、扩展性强大的常量、枚举类

2.订单号生成规则、订单严谨性判断

3.POJO和VO之间的实际操练

4.mybatis批量插入

posted on 2018-03-09 21:00  二十年后20  阅读(328)  评论(0编辑  收藏  举报

导航