從0開始 獨立完成企業級Java電商網站開發(服務端)筆記-購物車模塊功能

購物車功能:

1.加入購物車商品

2.更新購物車商品數量

3.查詢購物車商品數量

4.移除購物車商品

5.購物車商品單選/取消

6.購物車商品全選/取消

7.購物車列表

學習目標:

1.購物車模塊的設計思想

2.封裝一個高複用購物車核心方法

3.解決浮點型在商業運算中丟失精度問題(尤其是價格結計算)

數據表設計

接口設計

https://gitee.com/imooccode/happymmallwiki/wikis/%E9%97%A8%E6%88%B7_%E8%B4%AD%E7%89%A9%E8%BD%A6%E6%8E%A5%E5%8F%A3?sort_id=9919

limitQuantity:兩種狀態

--LIMIT_NUM_SUCCESS限制數量成功

--LIMIT_NUM_ERROR限制數量失敗

如果是限制數量失敗,會自動的把購物車中的產品數量進行修改,修改成最大值,也就是最大可購買的數量.應用場景:假設商品可購買數量是100個,當我們直接輸入200的時候超出商品庫存,就會返回一個LIMIT_NUM_ERROR,並把數量強制改回最大可購買數量如當前的100,並按可購數量計算總價.

那麼前端就可以根據該字段提示,已超出庫存,請進行修改.

 

實現:

購物車需要在用戶登錄狀態下進行操作.

 

1.購物車計算通用方法-購物車接口只要涉及到數量的變化都需要經過該方法,主要是用於防止超過庫存等一些注意操作

這個方法返回前端時都需要去調用的,用於向前端用戶返回最新的購物車數據.

場景:當在購物車添加商品時,

參數:productId商品ID,count數量

邏輯:

a-select:添加之前,需要去查詢當前用戶下,該productId是否在當前購物車.如果是空,說明該商品不再購物車,我們就要就該商品新增到購物車中.

b-insert:插入購物車數據表中,要將userId,商品id,數量count,同時設置當前商品的選中狀態checked=1(1是選中狀態);

c-update:如果a步驟查詢的是該商品已在該用戶的購物車中,那麼就是將購物車原有的數量加上現在加入購物車數量,並更新購物車數據表(也可同時將check狀態更新爲1,看需求);

 

基本思想是這個,但是我們額外還需要做一些操作,比如計算庫存等操作,防止前端和後端數據不一致.封裝高複用的購物車方法:

購物車產品組合的VO對象-CartProductVO(即已購物車表爲基礎進行擴展的表,比如根據userId可擴展一些用戶模塊信息,根據productId可擴展一些商品模塊信息)

CartProductVO:

id,userId,productId,quantity,productName,productSubtitle,productMainImage,productPrice,productStatus,productTotalPrice,productStock,productChecked,limitQuantity根據庫存限制返回數量字段

並且在整合CartProductVO後,在專門用一個針對cart購物車返回前端的VO-cartVO,這裏面集成了cartProductVO,並補充了一些通用字段:

CartVO:

List<CartProductVO> cartProductVO;

BigDecimal cartTotal;

Boolean allChecked;

String imageHost;

----將上述兩個對象封裝組合一個高複用的方法,返回給前端的CartVO對象.

 

private CartVO getCartVOList(int userId){

//根據userID查詢當前用戶購物車狀態

}

private CartVo getCartVoLimit(Integer userId){
		// 1 初始化返回前端的購物車VO對象
        CartVo cartVo = new CartVo();
		// 2 獲取該用戶購物車所有商品
        List<Cart> cartList = cartMapper.selectCartByUserId(userId);
		// 3 初始化cartProductVoList集合
        List<CartProductVo> cartProductVoList = Lists.newArrayList();
		// 4 處理浮點計算精度問題BigDecimal
        BigDecimal cartTotalPrice = new BigDecimal("0");
		// 5 用戶購物車不爲空時
        if(CollectionUtils.isNotEmpty(cartList)){
			// 6 取出該用戶購物車所有的商品,並放入CartProductVO對象重構 
            for(Cart cartItem : cartList){
				// 6-1 購物車基本信息
                CartProductVo cartProductVo = new CartProductVo();
                cartProductVo.setId(cartItem.getId());
                cartProductVo.setUserId(userId);
                cartProductVo.setProductId(cartItem.getProductId());
				// 6-2 購物車擴展數據-如商品對應的
                Product product = productMapper.selectByPrimaryKey(cartItem.getProductId());
                if(product != null){
                    cartProductVo.setProductMainImage(product.getMainImage());
                    cartProductVo.setProductName(product.getName());
                    cartProductVo.setProductSubtitle(product.getSubtitle());
                    cartProductVo.setProductStatus(product.getStatus());
                    cartProductVo.setProductPrice(product.getPrice());
                    cartProductVo.setProductStock(product.getStock());
                    // 6-2-1限制庫存,防止用戶加入購物車數量超過庫存數量
					//並將該數量用於計算購物車總價,保證總價的準確性
                    int buyLimitCount = 0;
                    if(product.getStock() >= cartItem.getQuantity()){
                        //庫存充足的時候
                        buyLimitCount = cartItem.getQuantity();
                        cartProductVo.setLimitQuantity(Const.Cart.LIMIT_NUM_SUCCESS);
                    }else{
						//超過庫存,那麼強制用戶加入購物車數量最大就是庫存數量
                        buyLimitCount = product.getStock();
						//同時返回超出庫存提示
                        cartProductVo.setLimitQuantity(Const.Cart.LIMIT_NUM_FAIL);
                        //更新購物車中有效數量-確保前後端購物車數量一致性
                        Cart cartForQuantity = new Cart();
                        cartForQuantity.setId(cartItem.getId());
                        cartForQuantity.setQuantity(buyLimitCount);
                        cartMapper.updateByPrimaryKeySelective(cartForQuantity);
                    }
					// 6-2-2將確認後的購物數量更新給前端,並用於計算商品總價
                    cartProductVo.setQuantity(buyLimitCount);
                    // 6-2-3計算當前商品總價
                    cartProductVo.setProductTotalPrice(BigDecimalUtil.mul(product.getPrice().doubleValue(),cartProductVo.getQuantity()));
                    cartProductVo.setProductChecked(cartItem.getChecked());
                }

                if(cartItem.getChecked() == Const.Cart.CHECKED){
                    //如果已經勾選,增加到整個的購物車總價中
                    cartTotalPrice = BigDecimalUtil.add(cartTotalPrice.doubleValue(),cartProductVo.getProductTotalPrice().doubleValue());
                }
                cartProductVoList.add(cartProductVo);
            }
        }
		// 7 數據填充到cartVO對象中
        cartVo.setCartTotalPrice(cartTotalPrice);
        cartVo.setCartProductVoList(cartProductVoList);
		// 是否全選
        cartVo.setAllChecked(this.getAllCheckedStatus(userId));
        cartVo.setImageHost(PropertiesUtil.getProperty("ftp.server.http.prefix"));
        return cartVo;
    }

	//傳遞userId去購物車數據表查詢是否未被勾選的-有未勾選的則標記爲false
    private boolean getAllCheckedStatus(Integer userId){
        if(userId == null){
            return false;
        }
        return cartMapper.selectCartProductCheckedStatusByUserId(userId) == 0;

    }

Tips:處理科學計算出現的浮點精度問題

處理科學計算浮點型數據是出現的微小精度問題,如價格,在Java中使用BigDecimal的String構造器進行計算,如 BigDecimal a = new BigDecimal("0.5"),然後和另一個String類型的BigDecimal變量進行計算纔不會出現精度錯誤.

Tips:一定是String的BigDecimal類型,如果用默認的依然會出現精度問題-new BigDecimal(5)

 

BigDecimal工具類-BigDecimalUtil,之後所有的運算都通過這個工具類轉化成BigDecimal進行計算

 

 

2.購物車添加商品

參數:productId商品ID,count數量

邏輯:

a-select:添加之前,需要去查詢當前用戶下,該productId是否在當前購物車.如果是空,說明該商品不再購物車,我們就要就該商品新增到購物車中.

b-insert:插入購物車數據表中,要將userId,商品id,數量count,同時設置當前商品的選中狀態checked=1(1是選中狀態);

c-update:如果a步驟查詢的是該商品已在該用戶的購物車中,那麼就是將購物車原有的數量加上現在加入購物車數量,並更新購物車數據表(也可同時將check狀態更新爲1,看需求);

 

3.更新購物車某個商品的數據量

參數:productId,count

需要更新增商品一樣,去判斷當前購物車是否有該商品

4.移除購物車某個產品

參數:productIds(商品ID可能同時有多個,不需要傳遞數量,直接刪除就好)

 

5.購物車List列表

參數:無

6.全選/全反選--其實就是更新update操作

參數:無,根據userId查詢全部購物車

Tips:有兩個接口全選接口和全反選接口,即調用全選接口時,後臺統一設置成選中;調用反選接口時,統一設置成不選中.然後在調用獲取全部購物車的list方法,得到最新的購物車數據.

 

7.單選/單獨反選

參數:productId,相較於上面的全選和不全選就是多了一個productID邏輯一樣

 

8.查詢當前用戶購物車裏面的產品數量(用於未進入購物車等頁面顯示購物車的數量)

根據產品加入購物車份數的累加

參數:無,查詢當前用戶下

返回:數值

Tips:用戶未登錄,不能報錯,只要返回數值0即可,即這裏判斷session時 不能因爲session.user爲空,就報錯,要返回0.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章