添加商品到购物车
This commit is contained in:
parent
d1cf736317
commit
5934fea2b9
@ -108,6 +108,12 @@
|
||||
<artifactId>redisson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.75</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
@ -5,4 +5,9 @@ public class CacheKey {
|
||||
* 注册验证码,第一个是类型,第二个是接收号码
|
||||
*/
|
||||
public final static String CHECK_CODE_KEY = "code:%s:%s";
|
||||
|
||||
/**
|
||||
* 购物车 hash 结果 , key是用户唯一标识
|
||||
*/
|
||||
public final static String CART_KEY = "cart:%s";
|
||||
}
|
||||
|
@ -14,61 +14,93 @@ public enum BizCodeEnum {
|
||||
*/
|
||||
OPS_REPEAT(110001, "重复操作"),
|
||||
|
||||
/**
|
||||
* 购物车
|
||||
*/
|
||||
CART_FILE(220001, "添加购物车失败"),
|
||||
|
||||
/**
|
||||
* 验证码
|
||||
*/
|
||||
CODE_TO_ERROR(240001, "接收号码不合规"),
|
||||
|
||||
CODE_LIMITED(240002, "验证码发送过快"),
|
||||
|
||||
CODE_ERROR(240003, "验证码错误"),
|
||||
|
||||
CODE_CAPTCHA(240101, "图形验证码错误"),
|
||||
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
ACCOUNT_REPEAT(250001, "账号已经存在"),
|
||||
|
||||
ACCOUNT_UNREGISTER(250002, "账号不存在"),
|
||||
|
||||
ACCOUNT_PWD_ERROR(250003, "账号或者密码错误"),
|
||||
|
||||
ACCOUNT_UNLOGIN(250004, "账号未登录"),
|
||||
|
||||
/**
|
||||
* 优惠券
|
||||
*/
|
||||
COUPON_CONDITION_ERROR(270001, "优惠券条件错误"),
|
||||
|
||||
COUPON_UNAVAILABLE(270002, "没有可用的优惠券"),
|
||||
|
||||
COUPON_NO_EXITS(270003, "优惠券不存在"),
|
||||
|
||||
COUPON_NO_STOCK(270005, "优惠券库存不足"),
|
||||
|
||||
COUPON_OUT_OF_LIMIT(270006, "优惠券领取超过限制次数"),
|
||||
|
||||
COUPON_OUT_OF_TIME(270407, "优惠券不在领取时间范围"),
|
||||
|
||||
COUPON_GET_FAIL(270407, "优惠券领取失败"),
|
||||
|
||||
COUPON_RECORD_LOCK_FAIL(270409, "优惠券锁定失败"),
|
||||
|
||||
/**
|
||||
* 订单
|
||||
*/
|
||||
ORDER_CONFIRM_COUPON_FAIL(280001, "创建订单-优惠券使用失败,不满足价格条件"),
|
||||
|
||||
ORDER_CONFIRM_PRICE_FAIL(280002, "创建订单-验价失败"),
|
||||
|
||||
ORDER_CONFIRM_LOCK_PRODUCT_FAIL(280003, "创建订单-商品库存不足锁定失败"),
|
||||
|
||||
ORDER_CONFIRM_ADD_STOCK_TASK_FAIL(280004, "创建订单-新增商品库存锁定任务"),
|
||||
|
||||
ORDER_CONFIRM_TOKEN_NOT_EXIST(280008, "订单令牌缺少"),
|
||||
|
||||
ORDER_CONFIRM_TOKEN_EQUAL_FAIL(280009, "订单令牌不正确"),
|
||||
|
||||
ORDER_CONFIRM_NOT_EXIST(280010, "订单不存在"),
|
||||
|
||||
ORDER_CONFIRM_CART_ITEM_NOT_EXIST(280011, "购物车商品项不存在"),
|
||||
|
||||
/**
|
||||
* 收货地址
|
||||
*/
|
||||
ADDRESS_ADD_FAIL(290001, "新增收货地址失败"),
|
||||
|
||||
ADDRESS_DEL_FAIL(290002, "删除收货地址失败"),
|
||||
|
||||
ADDRESS_NO_EXITS(290003, "地址不存在"),
|
||||
|
||||
/**
|
||||
* 支付
|
||||
*/
|
||||
PAY_ORDER_FAIL(300001, "创建支付订单失败"),
|
||||
|
||||
PAY_ORDER_CALLBACK_SIGN_FAIL(300002, "支付订单回调验证签失败"),
|
||||
|
||||
PAY_ORDER_CALLBACK_NOT_SUCCESS(300003, "创建支付订单失败"),
|
||||
|
||||
PAY_ORDER_NOT_EXIST(300005, "订单不存在"),
|
||||
|
||||
PAY_ORDER_STATE_ERROR(300006, "订单状态不正常"),
|
||||
|
||||
PAY_ORDER_PAY_TIMEOUT(300007, "订单支付超时"),
|
||||
|
||||
/**
|
||||
@ -76,7 +108,9 @@ public enum BizCodeEnum {
|
||||
*/
|
||||
|
||||
CONTROL_FLOW(500101, "限流控制"),
|
||||
|
||||
CONTROL_DEGRADE(500201, "降级控制"),
|
||||
|
||||
CONTROL_AUTH(500301, "认证控制"),
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ public class InterceptorConfig implements WebMvcConfigurer {
|
||||
registry
|
||||
.addInterceptor(new LoginInterceptor())
|
||||
//拦截的路径
|
||||
.addPathPatterns("")
|
||||
.addPathPatterns("api/cart/*/**")
|
||||
//放行的路径
|
||||
.excludePathPatterns("", "");
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
package net.jieyuu.controller;
|
||||
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import net.jieyuu.request.CartItemRequest;
|
||||
import net.jieyuu.service.CartService;
|
||||
import net.jieyuu.service.ProductService;
|
||||
import net.jieyuu.utils.JsonData;
|
||||
import net.jieyuu.vo.ProductVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author jieyuu
|
||||
* @since 2024-08-07
|
||||
*/
|
||||
|
||||
@Api("购物车")
|
||||
@RestController
|
||||
@RequestMapping("/api/cart/v1")
|
||||
public class CartController {
|
||||
|
||||
@Autowired
|
||||
private CartService cartService;
|
||||
|
||||
|
||||
@ApiOperation("添加到购物车")
|
||||
@PostMapping("add")
|
||||
public JsonData addToCart(@ApiParam("购物项") @RequestBody CartItemRequest cartItemRequest) {
|
||||
cartService.addToCart(cartItemRequest);
|
||||
return JsonData.buildSuccess();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -45,12 +45,12 @@ public class ProductDO implements Serializable {
|
||||
/**
|
||||
* 老价格
|
||||
*/
|
||||
private BigDecimal oldPrice;
|
||||
private BigDecimal oldAmount;
|
||||
|
||||
/**
|
||||
* 新价格
|
||||
*/
|
||||
private BigDecimal price;
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 库存
|
||||
|
@ -0,0 +1,21 @@
|
||||
package net.jieyuu.request;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@Data
|
||||
@ApiModel
|
||||
public class CartItemRequest {
|
||||
|
||||
|
||||
@ApiModelProperty(value = "商品id", example = "11")
|
||||
@JsonProperty("product_id")
|
||||
private long productId;
|
||||
|
||||
@ApiModelProperty(value = "购买数量", example = "11")
|
||||
@JsonProperty("buy_num")
|
||||
private int buyNum;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package net.jieyuu.service;
|
||||
|
||||
import net.jieyuu.request.CartItemRequest;
|
||||
|
||||
public interface CartService {
|
||||
/**
|
||||
* 添加商品到购物车
|
||||
* @param cartItemRequest
|
||||
*/
|
||||
public void addToCart(CartItemRequest cartItemRequest);
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package net.jieyuu.service.impl;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.jieyuu.constant.CacheKey;
|
||||
import net.jieyuu.enums.BizCodeEnum;
|
||||
import net.jieyuu.exception.BizException;
|
||||
import net.jieyuu.interceptor.LoginInterceptor;
|
||||
import net.jieyuu.model.LoginUser;
|
||||
import net.jieyuu.request.CartItemRequest;
|
||||
import net.jieyuu.service.CartService;
|
||||
import net.jieyuu.service.ProductService;
|
||||
import net.jieyuu.vo.CartItemVO;
|
||||
import net.jieyuu.vo.ProductVO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.BoundHashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CartServiceImpl implements CartService {
|
||||
|
||||
@Autowired
|
||||
private ProductService productService;
|
||||
@Autowired
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
@Override
|
||||
public void addToCart(CartItemRequest cartItemRequest) {
|
||||
long productId = cartItemRequest.getProductId();
|
||||
int buyNum = cartItemRequest.getBuyNum();
|
||||
|
||||
//获取购物车
|
||||
BoundHashOperations<String, Object, Object> myCart = getMyCartOps();
|
||||
|
||||
Object cacheObj = myCart.get(productId);
|
||||
String result = "";
|
||||
|
||||
if (cacheObj != null) {
|
||||
result = (String) cacheObj;
|
||||
}
|
||||
if (StringUtils.isBlank(result)) {
|
||||
//不存在
|
||||
|
||||
CartItemVO cartItemVO = new CartItemVO();
|
||||
|
||||
ProductVO productVO = productService.findDetailById(productId);
|
||||
|
||||
if (productVO == null) {
|
||||
throw new BizException(BizCodeEnum.CART_FILE);
|
||||
}
|
||||
|
||||
cartItemVO.setAmount(productVO.getAmount());
|
||||
cartItemVO.setBuyNum(buyNum);
|
||||
cartItemVO.setProductId(productId);
|
||||
cartItemVO.setProductImg(productVO.getCoverImg());
|
||||
cartItemVO.setProductTitle(productVO.getTitle());
|
||||
|
||||
myCart.put(productId, JSON.toJSONString(cartItemVO));
|
||||
} else {
|
||||
//存在商品,修改购物车
|
||||
CartItemVO cartItem = JSON.parseObject(result, CartItemVO.class);
|
||||
cartItem.setBuyNum(cartItem.getBuyNum() + buyNum);
|
||||
myCart.put(productId, JSON.toJSONString(cartItem));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽取购物车 通用方法
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private BoundHashOperations<String, Object, Object> getMyCartOps() {
|
||||
String cartKey = getCartKey();
|
||||
return redisTemplate.boundHashOps(cartKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 购物车 key
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String getCartKey() {
|
||||
LoginUser loginUser = LoginInterceptor.threadLocal.get();
|
||||
String cartKey = String.format(CacheKey.CART_KEY, loginUser.getId());
|
||||
|
||||
return cartKey;
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package net.jieyuu.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class CartItemVO {
|
||||
|
||||
/**
|
||||
* 商品id
|
||||
*/
|
||||
@JsonProperty("product_id")
|
||||
private Long productId;
|
||||
|
||||
/**
|
||||
* 购买数量
|
||||
*/
|
||||
@JsonProperty("buy_num")
|
||||
private Integer buyNum;
|
||||
/**
|
||||
* 商品标题
|
||||
*/
|
||||
@JsonProperty("product_title")
|
||||
private String productTitle;
|
||||
/**
|
||||
* 商品图片
|
||||
*/
|
||||
@JsonProperty("product_img")
|
||||
private String productImg;
|
||||
|
||||
/**
|
||||
* 商品单价
|
||||
*/
|
||||
private BigDecimal amount;
|
||||
/**
|
||||
* 商品总价
|
||||
*/
|
||||
@JsonProperty("total_amount")
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
|
||||
public Long getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
public void setProductId(Long productId) {
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
|
||||
public Integer getBuyNum() {
|
||||
return buyNum;
|
||||
}
|
||||
|
||||
public void setBuyNum(Integer buyNum) {
|
||||
this.buyNum = buyNum;
|
||||
}
|
||||
|
||||
public String getProductTitle() {
|
||||
return productTitle;
|
||||
}
|
||||
|
||||
public void setProductTitle(String productTitle) {
|
||||
this.productTitle = productTitle;
|
||||
}
|
||||
|
||||
public String getProductImg() {
|
||||
return productImg;
|
||||
}
|
||||
|
||||
public void setProductImg(String productImg) {
|
||||
this.productImg = productImg;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品总价 * 商品数量
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getTotalAmount() {
|
||||
return this.amount.multiply(new BigDecimal(this.buyNum));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package net.jieyuu.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
public class CartVO {
|
||||
@JsonProperty("cart_items")
|
||||
private List<CartItemVO> cartItems;
|
||||
|
||||
|
||||
@JsonProperty("total_num")
|
||||
private Integer totalNum;
|
||||
@JsonProperty("total_amount")
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
@JsonProperty("real_pay_amount")
|
||||
private BigDecimal realPayAmount;
|
||||
|
||||
public void setCartItems(List<CartItemVO> cartItems) {
|
||||
this.cartItems = cartItems;
|
||||
}
|
||||
|
||||
public List<CartItemVO> getCartItems() {
|
||||
return cartItems;
|
||||
}
|
||||
|
||||
public Integer getTotalNum() {
|
||||
if (this.cartItems != null) {
|
||||
int total = cartItems.stream().mapToInt(CartItemVO::getBuyNum).sum();
|
||||
return total;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 总价格
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getTotalAmount() {
|
||||
BigDecimal amount = new BigDecimal("0");
|
||||
|
||||
if (this.cartItems != null) {
|
||||
for (CartItemVO cartItem : cartItems) {
|
||||
BigDecimal itemTotalAmount = cartItem.getTotalAmount();
|
||||
amount = amount.add(itemTotalAmount);
|
||||
}
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实际价格
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BigDecimal getRealPayAmount() {
|
||||
BigDecimal amount = new BigDecimal("0");
|
||||
if (this.cartItems != null) {
|
||||
for (CartItemVO cartItem : cartItems) {
|
||||
BigDecimal itemTotalAmount = cartItem.getAmount();
|
||||
amount = amount.add(itemTotalAmount);
|
||||
}
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
}
|
@ -41,13 +41,13 @@ public class ProductVO {
|
||||
/**
|
||||
* 老价格
|
||||
*/
|
||||
@JsonProperty("old_price")
|
||||
private BigDecimal oldPrice;
|
||||
@JsonProperty("old_amount")
|
||||
private BigDecimal oldAmount;
|
||||
|
||||
/**
|
||||
* 新价格
|
||||
*/
|
||||
private BigDecimal price;
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 库存
|
||||
|
@ -8,8 +8,8 @@
|
||||
<result column="title" property="title" />
|
||||
<result column="cover_img" property="coverImg" />
|
||||
<result column="detail" property="detail" />
|
||||
<result column="old_price" property="oldPrice" />
|
||||
<result column="price" property="price" />
|
||||
<result column="old_amount" property="oldAmount" />
|
||||
<result column="amount" property="amount" />
|
||||
<result column="stock" property="stock" />
|
||||
<result column="create_time" property="createTime" />
|
||||
<result column="lock_stock" property="lockStock" />
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
id, title, cover_img, detail, old_price, price, stock, create_time, lock_stock
|
||||
id, title, cover_img, detail, old_amount, amount, stock, create_time, lock_stock
|
||||
</sql>
|
||||
|
||||
</mapper>
|
||||
|
Loading…
Reference in New Issue
Block a user