下單


業務分析

點擊提交訂單的時候,會立即創建訂單數據,創建訂單數據會將數據存入到2張表中,分別是訂單表和訂單明細表,此處還需要修改商品對應的庫存數量。

訂單表結構如下:

CREATE TABLE `tb_order` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '訂單id',
  `total_num` int(11) DEFAULT NULL COMMENT '數量合計',
  `total_money` int(11) DEFAULT NULL COMMENT '金額合計',
  `pre_money` int(11) DEFAULT NULL COMMENT '優惠金額',
  `post_fee` int(11) DEFAULT NULL COMMENT '郵費',
  `pay_money` int(11) DEFAULT NULL COMMENT '實付金額',
  `pay_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付類型,1、在線支付、0 貨到付款',
  `create_time` datetime DEFAULT NULL COMMENT '訂單創建時間',
  `update_time` datetime DEFAULT NULL COMMENT '訂單更新時間',
  `pay_time` datetime DEFAULT NULL COMMENT '付款時間',
  `consign_time` datetime DEFAULT NULL COMMENT '發貨時間',
  `end_time` datetime DEFAULT NULL COMMENT '交易完成時間',
  `close_time` datetime DEFAULT NULL COMMENT '交易關閉時間',
  `shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名稱',
  `shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流單號',
  `username` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用戶名稱',
  `buyer_message` varchar(1000) COLLATE utf8_bin DEFAULT NULL COMMENT '買家留言',
  `buyer_rate` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否評價',
  `receiver_contact` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收貨人',
  `receiver_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收貨人手機',
  `receiver_address` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '收貨人地址',
  `source_type` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '訂單來源:1:web,2:app,3:微信公眾號,4:微信小程序  5 H5手機頁面',
  `transaction_id` varchar(30) COLLATE utf8_bin DEFAULT NULL COMMENT '交易流水號',
  `order_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '訂單狀態,0:未完成,1:已完成,2:已退貨',
  `pay_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付狀態,0:未支付,1:已支付,2:支付失敗',
  `consign_status` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '發貨狀態,0:未發貨,1:已發貨,2:已收貨',
  `is_delete` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否刪除',
  PRIMARY KEY (`id`),
  KEY `create_time` (`create_time`),
  KEY `status` (`order_status`),
  KEY `payment_type` (`pay_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

訂單明細表結構如下:

CREATE TABLE `tb_order_item` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'ID',
  `category_id1` int(11) DEFAULT NULL COMMENT '1級分類',
  `category_id2` int(11) DEFAULT NULL COMMENT '2級分類',
  `category_id3` int(11) DEFAULT NULL COMMENT '3級分類',
  `spu_id` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT 'SPU_ID',
  `sku_id` bigint(20) NOT NULL COMMENT 'SKU_ID',
  `order_id` bigint(20) NOT NULL COMMENT '訂單ID',
  `name` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品名稱',
  `price` int(20) DEFAULT NULL COMMENT '單價',
  `num` int(10) DEFAULT NULL COMMENT '數量',
  `money` int(20) DEFAULT NULL COMMENT '總金額',
  `pay_money` int(11) DEFAULT NULL COMMENT '實付金額',
  `image` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '圖片地址',
  `weight` int(11) DEFAULT NULL COMMENT '重量',
  `post_fee` int(11) DEFAULT NULL COMMENT '運費',
  `is_return` char(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否退貨,0:未退貨,1:已退貨',
  PRIMARY KEY (`id`),
  KEY `item_id` (`sku_id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

下單實現

下單的時候,先往tb_order表中增加數據,再往tb_order_item表中增加數據。

代碼實現

這里先修改changgou-service-order微服務,實現下單操作,這里會生成訂單號,我們首先需要在啟動類中創建一個IdWorker對象。

com.changgou.OrderApplication中創建IdWorker,代碼如下:

@Bean
public IdWorker idWorker(){
    return new IdWorker(1,1);
}

(1)控制層

修改changgou-service-order微服務,修改com.changgou.order.controller.OrderController類,代碼如下:

@Autowired
private TokenDecode tokenDecode;
​
/***
 * 新增Order數據
 * @param order
 * @return
 */
@PostMapping
public Result add(@RequestBody Order order){
    //獲取用戶名
    Map<String, String> userMap = tokenDecode.getUserInfo();
    String username = userMap.get("username");
    //設置購買用戶
    order.setUsername(username);
    orderService.add(order);
    return new Result(true,StatusCode.OK,"添加成功");
}

(2)業務層

實現邏輯:

1)獲取所有購物項

2)統計計算:總金額,總數量

3)填充訂單數據並保存

4)獲取每一個購物項保存到orderItem

5)刪除購物車中數據

修改訂單微服務添加com.changgou.order.service.impl.OrderServiceImpl,代碼如下:

 /**
     * 增加
     * @param order
     */
    @Override
    public void add(Order order){
        //1)獲取所有購物項
        Map cartMap = cartService.list(order.getUsername());
        List<OrderItem> orderItemList = (List<OrderItem>) cartMap.get("orderItemList");
        //3)填充訂單數據並保存
        order.setTotalNum((Integer) cartMap.get("totalNum"));
        order.setTotalMoney((Integer) cartMap.get("totalMoney"));
        order.setPayMoney((Integer) cartMap.get("totalMoney"));
        order.setCreateTime(new Date());
        order.setUpdateTime(order.getCreateTime());
        order.setBuyerRate("0");        //0:未評價,1:已評價
        order.setSourceType("1");       //來源,1:WEB
        order.setOrderStatus("0");      //0:未完成,1:已完成,2:已退貨
        order.setPayStatus("0");        //0:未支付,1:已支付,2:支付失敗
        order.setConsignStatus("0");    //0:未發貨,1:已發貨,2:已收貨
        order.setId(idWorker.nextId()+"");
        int count = orderMapper.insertSelective(order);
​
        //添加訂單明細
        for (OrderItem orderItem : orderItemList) {
            orderItem.setId(idWorker.nextId()+"");
            orderItem.setIsReturn("0");
            orderItem.setOrderId(order.getId());
            orderItemMapper.insertSelective(orderItem);
        }
​
        //清除Redis緩存購物車數據
        redisTemplate.delete("Cart_"+order.getUsername());
    }

渲染服務對接

我們需要在模板渲染端調用訂單微服務實現下單操作,下單操作需要調用訂單微服務,所以需要創建對應的Feign。

(1)Feign創建

修改changgou-service-order-api,添加OrderFeign,代碼如下:

@FeignClient(name="order")
public interface OrderFeign {
    /***
     * 提交訂單數據
     * @param order
     * @return
     */
     @PostMapping("/order")
    Result add(@RequestBody Order order);
}

(2)下單調用

修改changgou-web-order的com.changgou.order.controller.OrderController添加下單方法,代碼如下:

@Autowired
private OrderFeign orderFeign;
​
/***
 * 添加訂單數據到購物車中
 * @param order
 * @return
 */
@PostMapping(value = "/add")
@ResponseBody
public Result add(@RequestBody Order order){
   Result result = orderFeign.add(order);
   return  result;
}

(3)頁面調用

修改order.html,增加下單js方法,並且在頁面點擊下單調用,代碼如下:

點擊提交訂單調用

保存訂單測試,表數據變化如下:

tb_order表數據:

tb_order_item表數據:

庫存變更

業務分析

上面操作只實現了下單操作,但對應的庫存還沒跟着一起減少,我們在下單之后,應該調用商品微服務,將下單的商品庫存減少,銷量增加。每次訂單微服務只需要將用戶名傳到商品微服務,商品微服務通過用戶名到Redis中查詢對應的購物車數據,然后執行庫存減少,庫存減少需要控制當前商品庫存>=銷售數量。

如何控制庫存數量>=購買數量呢?其實可以通過SQL語句實現,每次減少數量之前,加個條件判斷。

where num>=#{num}即可。

商品服務需要查詢購物車數據,所以需要引入訂單的api,在pom.xml中添加如下依賴:

<!--order api 依賴-->
<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou_service_order_api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

代碼實現

要調用其他微服務,需要將頭文件中的令牌數據攜帶到其他微服務中取,所以我們不能使用hystrix的多線程模式,修改changgou-service-order的applicatin.yml配置,代碼如下:

#hystrix 配置
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000
          strategy: SEMAPHORE

每次還需要使用攔截器添加頭文件信息,修改配置類com.changgou.OrderApplication添加攔截器,代碼如下:

@Bean
public FeignInterceptor feignInterceptor(){
    return new FeignInterceptor();
}

(1)Dao層

修改changgou-service-goods微服務的com.changgou.goods.dao.SkuMapper接口,增加庫存遞減方法,代碼如下:

/**
 * 遞減庫存
 * @param orderItem
 * @return
 */
@Update("UPDATE tb_sku SET num=num-#{num},sale_num=sale_num+#{num} WHERE id=#{skuId} AND num>=#{num}")
int decrCount(OrderItem orderItem);

(2)業務層

修改changgou-service-order微服務的com.changgou.goods.service.SkuService接口,添加如下方法:

/***
 * 庫存遞減
 * @param username
 */
void decrCount(String username);

修改changgou-service-order微服務的com.changgou.goods.service.impl.SkuServiceImpl實現類,添加一個實現方法,代碼如下:

@Autowired
private RedisTemplate redisTemplate;
​
/***
 * 庫存遞減
 * @param username
 */
@Override
public void decrCount(String username) {
    //獲取購物車數據
    List<OrderItem> orderItems = redisTemplate.boundHashOps("Cart_" + username).values();
​
    //循環遞減
    for (OrderItem orderItem : orderItems) {
        //遞減庫存
        int count = skuMapper.decrCount(orderItem);
        if(count<=0){
            throw new RuntimeException("庫存不足,遞減失敗!");
        }
    }
}

(3)控制層

修改changgou-service-goods的com.changgou.goods.controller.SkuController類,添加庫存遞減方法,代碼如下:

/***
 * 庫存遞減
 * @param username
 * @return
 */
@PostMapping(value = "/decr/count")
public Result decrCount(@RequestParam("username") String username){
    //庫存遞減
    skuService.decrCount(username);
    return new Result(true,StatusCode.OK,"庫存遞減成功!");
}

(4)創建feign

同時在changgou-service-goods-api工程添加com.changgou.goods.feign.SkuFeign的實現,代碼如下:

/***
 * 庫存遞減
 * @param username
 * @return
 */
@PostMapping(value = "/decr/count")
Result decrCount(@RequestParam(value = "username") String username);

調用庫存遞減

修改changgou-service-order微服務的com.changgou.order.service.impl.OrderServiceImpl類的add方法,增加庫存遞減的調用。

先注入SkuFeign

@Autowired
private SkuFeign skuFeign;

再調用庫存遞減方法

//庫存減庫存
skuFeign.decrCount(order.getUsername());

完整代碼如下:

測試

庫存減少前,查詢數據庫Sku數據如下:個數98,銷量0

使用Postman執行 http://localhost:18081/api/order/add

執行測試后,剩余庫存97,銷量1

增加積分(學員練習)

比如每次下單完成之后,給用戶增加10個積分,支付完成后贈送優惠券,優惠券可用於支付時再次抵扣。我們先完成增加積分功能。如下表:points表示用戶積分

CREATE TABLE `tb_user` (
  `username` varchar(50) NOT NULL COMMENT '用戶名',
  `password` varchar(100) NOT NULL COMMENT '密碼,加密存儲',
  `phone` varchar(20) DEFAULT NULL COMMENT '注冊手機號',
  `email` varchar(50) DEFAULT NULL COMMENT '注冊郵箱',
  `created` datetime NOT NULL COMMENT '創建時間',
  `updated` datetime NOT NULL COMMENT '修改時間',
  `source_type` varchar(1) DEFAULT NULL COMMENT '會員來源:1:PC,2:H5,3:Android,4:IOS',
  `nick_name` varchar(50) DEFAULT NULL COMMENT '昵稱',
  `name` varchar(50) DEFAULT NULL COMMENT '真實姓名',
  `status` varchar(1) DEFAULT NULL COMMENT '使用狀態(1正常 0非正常)',
  `head_pic` varchar(150) DEFAULT NULL COMMENT '頭像地址',
  `qq` varchar(20) DEFAULT NULL COMMENT 'QQ號碼',
  `is_mobile_check` varchar(1) DEFAULT '0' COMMENT '手機是否驗證 (0否  1是)',
  `is_email_check` varchar(1) DEFAULT '0' COMMENT '郵箱是否檢測(0否  1是)',
  `sex` varchar(1) DEFAULT '1' COMMENT '性別,1男,0女',
  `user_level` int(11) DEFAULT NULL COMMENT '會員等級',
  `points` int(11) DEFAULT NULL COMMENT '積分',
  `experience_value` int(11) DEFAULT NULL COMMENT '經驗值',
  `birthday` datetime DEFAULT NULL COMMENT '出生年月日',
  `last_login_time` datetime DEFAULT NULL COMMENT '最后登錄時間',
  PRIMARY KEY (`username`),
  UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶表';

代碼實現

(1)dao層

修改changgou-service-user微服務的com.changgou.user.dao.UserMapper接口,增加用戶積分方法,代碼如下:

/***
 * 增加用戶積分
 * @param username
 * @param pint
 * @return
 */
@Update("UPDATE tb_user SET points=points+#{point} WHERE  username=#{username}")
int addUserPoints(@Param("username") String username, @Param("point") Integer pint);

(2)業務層

修改changgou-service-user微服務的com.changgou.user.service.UserService接口,代碼如下:

/***
 * 添加用戶積分
 * @param username
 * @param pint
 * @return
 */
int addUserPoints(String username,Integer pint);

修改changgou-service-user微服務的com.changgou.user.service.impl.UserServiceImpl,增加添加積分方法實現,代碼如下:

/***
 * 修改用戶積分
 * @param username
 * @param pint
 * @return
 */
@Override
public int addUserPoints(String username, Integer pint) {
    return userMapper.addUserPoints(username,pint);
}

(3)控制層

修改changgou-service-user微服務的com.changgou.user.controller.UserController,添加增加用戶積分方法,代碼如下:

@Autowired
private TokenDecode tokenDecode;
​
/***
 * 增加用戶積分
 * @param points:要添加的積分
 */
@GetMapping(value = "/points/add")
public Result addPoints(Integer points){
    //獲取用戶名
    Map<String, String> userMap = tokenDecode.getUserInfo();
    String username = userMap.get("username");
​
    //添加積分
    userService.addUserPoints(username,points);
    return new Result(true,StatusCode.OK,"添加積分成功!");
}

(4)Feign添加

修改changgou-service-user-api工程,修改com.changgou.user.feign.UserFeign,添加增加用戶積分方法,代碼如下:

/***
 * 添加用戶積分
 * @param points
 * @return
 */
@GetMapping(value = "/points/add")
Result addPoints(@RequestParam(value = "points")Integer points);

 增加積分調用

修改changgou-service-order,添加changgou-service-user-api的依賴,修改pom.xml,添加如下依賴:

<!--user api 依賴-->
<dependency>
    <groupId>com.changgou</groupId>
    <artifactId>changgou-service-user-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在增加訂單的時候,同時添加用戶積分,修改changgou-service-order微服務的com.changgou.order.service.impl.OrderServiceImpl下單方法,增加調用添加積分方法,代碼如下:

修改changgou-service-order的啟動類com.changgou.OrderApplication,添加feign的包路徑:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM