feat: 添加商城相关操作
This commit is contained in:
parent
cada4dbe49
commit
5463c1e60c
@ -0,0 +1,28 @@
|
|||||||
|
package me.xiaoyan.point.api.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import me.xiaoyan.point.api.pojo.Goods;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.PageParam;
|
||||||
|
import me.xiaoyan.point.api.service.GoodsService;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("shop/goods")
|
||||||
|
public class ShopGoodsController {
|
||||||
|
@Resource
|
||||||
|
private GoodsService goodsService;
|
||||||
|
|
||||||
|
@GetMapping("query")
|
||||||
|
public Page<Goods> query(
|
||||||
|
int category,
|
||||||
|
int page,
|
||||||
|
int pageSize
|
||||||
|
) {
|
||||||
|
return goodsService.queryByPage(category, Page.of(page, pageSize));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package me.xiaoyan.point.api.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import me.xiaoyan.point.api.error.BizException;
|
||||||
|
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.CreateOrderData;
|
||||||
|
import me.xiaoyan.point.api.service.GoodsService;
|
||||||
|
import me.xiaoyan.point.api.service.OrderInfoService;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单表(OrderInfo)表控制层
|
||||||
|
*
|
||||||
|
* @author makejava
|
||||||
|
* @since 2022-11-24 09:32:38
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("shop/order")
|
||||||
|
public class ShopOrderInfoController {
|
||||||
|
@Resource
|
||||||
|
private OrderInfoService orderInfoService;
|
||||||
|
@Resource
|
||||||
|
private GoodsService goodsService;
|
||||||
|
@Resource
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
// 是否已经没有库存
|
||||||
|
private ConcurrentHashMap<Integer, Boolean> stockOutMap = new ConcurrentHashMap<>();
|
||||||
|
private static final String CACHE_STOCK_KEY = "goods:stock:";
|
||||||
|
|
||||||
|
private String cacheKey(long gid) {
|
||||||
|
return CACHE_STOCK_KEY + gid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct // 初始化执行一次
|
||||||
|
private void initGoodsStockCache() {
|
||||||
|
//TODO 应该定时更新缓存数据
|
||||||
|
goodsService.queryAllGoodsIdAndStock().forEach(g -> {
|
||||||
|
log.info("缓存 id:{} stock:{} ", g.getId(), g.getStock());
|
||||||
|
// 缓存库存
|
||||||
|
stringRedisTemplate.opsForValue().set(cacheKey(g.getId()), g.getStock().toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("create")
|
||||||
|
public OrderInfo create(@Validated @RequestBody CreateOrderData data) {
|
||||||
|
if (data.getGoodsId() <= 0 || data.getBuyCount() <= 0) {
|
||||||
|
throw BizException.create("订单参数不正确");
|
||||||
|
}
|
||||||
|
//1.内存判断
|
||||||
|
if (stockOutMap.get(data.getGoodsId())) {
|
||||||
|
throw BizException.create("库存不足");
|
||||||
|
}
|
||||||
|
//2.缓存(redis)判断
|
||||||
|
long count = stringRedisTemplate.opsForValue().decrement(cacheKey(data.getGoodsId()));
|
||||||
|
if (count < 0) {
|
||||||
|
// 此时库存没有了 , 保存到已买完的对象
|
||||||
|
stockOutMap.put(data.getGoodsId(),true);
|
||||||
|
log.info("stock count ===>" + count);
|
||||||
|
// 对缓存进行库存 + 1
|
||||||
|
stringRedisTemplate.opsForValue().increment(cacheKey(data.getGoodsId())); //
|
||||||
|
throw BizException.create("库存不足");
|
||||||
|
}
|
||||||
|
//3.数据库
|
||||||
|
return orderInfoService.create(StpUtil.getLoginIdAsInt(), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
package me.xiaoyan.point.api.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import me.xiaoyan.point.api.pojo.Goods;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity me.xiaoyan.point.api.pojo.Goods
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface GoodsMapper extends BaseMapper<Goods> {
|
||||||
|
public Page<Goods> queryByCategory(@Param("category") int category,Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扣除商品库存
|
||||||
|
* @param id
|
||||||
|
* @param count
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int deductCount(@Param("id") int id, @Param("count") int count);
|
||||||
|
public List<Goods> queryAllGoodsIdAndStock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
|||||||
|
package me.xiaoyan.point.api.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单表(OrderInfo)表数据库访问层
|
||||||
|
*
|
||||||
|
* @author makejava
|
||||||
|
* @since 2022-11-24 09:32:38
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
107
api/src/main/java/me/xiaoyan/point/api/pojo/Goods.java
Normal file
107
api/src/main/java/me/xiaoyan/point/api/pojo/Goods.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品表
|
||||||
|
* @TableName goods
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@TableName(value ="goods")
|
||||||
|
public class Goods implements Serializable {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类别(1:普通 2:精选 3:秒杀 4:抽奖)
|
||||||
|
*/
|
||||||
|
private Integer category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品类型(1:实物 2:虚拟)
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原价
|
||||||
|
*/
|
||||||
|
private Integer originPrice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 价格
|
||||||
|
*/
|
||||||
|
private Integer price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 库存数量
|
||||||
|
*/
|
||||||
|
private Integer stock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 购买最大数量(0表示不限制)
|
||||||
|
*/
|
||||||
|
private Integer limitCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品图
|
||||||
|
*/
|
||||||
|
private String cover;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示
|
||||||
|
*/
|
||||||
|
private String notice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上架时间
|
||||||
|
*/
|
||||||
|
private Date onlineTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下架时间
|
||||||
|
*/
|
||||||
|
private Date offlineTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
}
|
50
api/src/main/java/me/xiaoyan/point/api/pojo/OrderInfo.java
Normal file
50
api/src/main/java/me/xiaoyan/point/api/pojo/OrderInfo.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单表(OrderInfo)表实体类
|
||||||
|
*
|
||||||
|
* @author makejava
|
||||||
|
* @since 2022-11-24 09:32:42
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@TableName(value ="order_info")
|
||||||
|
public class OrderInfo {
|
||||||
|
@TableId
|
||||||
|
//订单编号
|
||||||
|
private String id;
|
||||||
|
//商品编号
|
||||||
|
private Long gid;
|
||||||
|
//价格
|
||||||
|
private Integer price;
|
||||||
|
//购买数量
|
||||||
|
private Integer count;
|
||||||
|
//用户编号
|
||||||
|
private Integer uid;
|
||||||
|
//订单数据
|
||||||
|
private String data;
|
||||||
|
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
private Date updateTime;
|
||||||
|
//订单状态(0:已删除 1:已取消 2:待确认 3:已完成)
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo.dto;
|
||||||
|
|
||||||
|
public class OrderStatus {
|
||||||
|
public static final int DELETE = 0;
|
||||||
|
public static final int CANCEL = 1;
|
||||||
|
public static final int CONFIRM = 2;
|
||||||
|
public static final int DONE = 3;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package me.xiaoyan.point.api.pojo.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CreateOrderData implements Serializable {
|
||||||
|
private int goodsId;
|
||||||
|
private int buyCount;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package me.xiaoyan.point.api.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import me.xiaoyan.point.api.pojo.Goods;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.PageParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface GoodsService extends IService<Goods> {
|
||||||
|
|
||||||
|
Page<Goods> queryByPage(int category, Page page);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 减库存
|
||||||
|
* @param id
|
||||||
|
* @param count
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean deductStock(int id,int count);
|
||||||
|
|
||||||
|
List<Goods> queryAllGoodsIdAndStock();
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package me.xiaoyan.point.api.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.CreateOrderData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单表(OrderInfo)表服务接口
|
||||||
|
*
|
||||||
|
* @author makejava
|
||||||
|
* @since 2022-11-24 09:32:44
|
||||||
|
*/
|
||||||
|
public interface OrderInfoService extends IService<OrderInfo> {
|
||||||
|
|
||||||
|
OrderInfo create(int uid, CreateOrderData data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
package me.xiaoyan.point.api.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import me.xiaoyan.point.api.pojo.Goods;
|
||||||
|
import me.xiaoyan.point.api.service.GoodsService;
|
||||||
|
import me.xiaoyan.point.api.mapper.GoodsMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods>
|
||||||
|
implements GoodsService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<Goods> queryByPage(int category, Page page) {
|
||||||
|
return this.getBaseMapper().queryByCategory(category, page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deductStock(int id, int count) {
|
||||||
|
return getBaseMapper().deductCount(id,count) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Goods> queryAllGoodsIdAndStock() {
|
||||||
|
return getBaseMapper().queryAllGoodsIdAndStock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
|||||||
|
package me.xiaoyan.point.api.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import me.xiaoyan.point.api.error.BizException;
|
||||||
|
import me.xiaoyan.point.api.mapper.OrderInfoMapper;
|
||||||
|
import me.xiaoyan.point.api.pojo.Goods;
|
||||||
|
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||||
|
import me.xiaoyan.point.api.pojo.dto.OrderStatus;
|
||||||
|
import me.xiaoyan.point.api.pojo.vo.CreateOrderData;
|
||||||
|
import me.xiaoyan.point.api.service.GoodsService;
|
||||||
|
import me.xiaoyan.point.api.service.OrderInfoService;
|
||||||
|
import me.xiaoyan.point.api.service.UserInfoService;
|
||||||
|
import me.xiaoyan.point.api.util.OrderIdGenerator;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单表(OrderInfo)表服务实现类
|
||||||
|
*
|
||||||
|
* @author makejava
|
||||||
|
* @since 2022-11-24 09:32:44
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserInfoService userInfoService;
|
||||||
|
@Resource
|
||||||
|
private GoodsService goodsService;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public OrderInfo create(int uid, CreateOrderData data) {
|
||||||
|
// 1.查询用户信息
|
||||||
|
final UserInfo user = userInfoService.getInfoById(uid);
|
||||||
|
// 判断用户信息
|
||||||
|
if (user == null) throw BizException.create("用户信息不存在");
|
||||||
|
if (user.getStatus() != 1) throw BizException.create("用户状态不正确");
|
||||||
|
// 2.查询商品信息
|
||||||
|
final Goods goods = goodsService.getById(data.getGoodsId());
|
||||||
|
if (goods == null) throw BizException.create("兑换的商品不存在");
|
||||||
|
long now = new Date().getTime();
|
||||||
|
if (goods.getOnlineTime().getTime() > now || goods.getOfflineTime().getTime() < now) {
|
||||||
|
throw BizException.create("商品未上架或已下架");
|
||||||
|
}
|
||||||
|
if (goods.getStock() < data.getBuyCount()) throw BizException.create("商品存库不足");
|
||||||
|
// 判断购买数量的限制
|
||||||
|
if(buyHistoryCount(uid,data.getGoodsId()) + data.getBuyCount() > goods.getLimitCount()){
|
||||||
|
throw BizException.create("最多兑换" + goods.getLimitCount() + "件");
|
||||||
|
}
|
||||||
|
// 3.减库存
|
||||||
|
if (!goodsService.deductStock(data.getGoodsId(), data.getBuyCount())) {
|
||||||
|
throw BizException.create("商品库存不足");
|
||||||
|
}
|
||||||
|
// 4.创建订单
|
||||||
|
OrderInfo orderInfo = OrderInfo.builder()
|
||||||
|
.id(OrderIdGenerator.next())
|
||||||
|
.gid((long) data.getGoodsId())
|
||||||
|
.uid(uid)
|
||||||
|
.count(data.getBuyCount())
|
||||||
|
.price(goods.getPrice())
|
||||||
|
.status(OrderStatus.CONFIRM)
|
||||||
|
.build();
|
||||||
|
if (save(orderInfo)) {
|
||||||
|
return orderInfo;
|
||||||
|
}
|
||||||
|
throw BizException.create("创建订单失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
public long buyHistoryCount(int uid, int gid) {
|
||||||
|
QueryWrapper q = new QueryWrapper();
|
||||||
|
q.eq("uid", gid);
|
||||||
|
q.eq("gid", gid);
|
||||||
|
q.ge("status", OrderStatus.CONFIRM); // 状态为2(待确认)和3(已完成)
|
||||||
|
return count(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
package me.xiaoyan.point.api.util;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class OrderIdGenerator {
|
||||||
|
private static AtomicInteger atomic = new AtomicInteger();
|
||||||
|
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss");
|
||||||
|
private static long prevTime = 0;
|
||||||
|
|
||||||
|
public static String next() {
|
||||||
|
long now = System.currentTimeMillis() / 1000;
|
||||||
|
if (now > prevTime) {
|
||||||
|
prevTime = now;
|
||||||
|
atomic.set(0);
|
||||||
|
}
|
||||||
|
return dateFormat.format(new Date()) + String.format("%05d", atomic.addAndGet(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
System.out.println(next());
|
||||||
|
Thread.sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,7 @@ create table point_record
|
|||||||
point int(10) not null,
|
point int(10) not null,
|
||||||
current_total_point int(10) not null,
|
current_total_point int(10) not null,
|
||||||
reason varchar(100) not null,
|
reason varchar(100) not null,
|
||||||
valid_time datetime default current_timestamp,
|
valid_time datetime default current_timestamp,
|
||||||
expire_time datetime null
|
expire_time datetime null
|
||||||
) engine = innodb comment '积分记录表';
|
) engine = innodb comment '积分记录表';
|
||||||
|
|
||||||
@ -41,10 +41,38 @@ create table sign_record
|
|||||||
uid int(10) not null,
|
uid int(10) not null,
|
||||||
point int(10) not null,
|
point int(10) not null,
|
||||||
ip varchar(50) not null,
|
ip varchar(50) not null,
|
||||||
create_time datetime default current_timestamp
|
create_time datetime default current_timestamp
|
||||||
) engine = innodb comment '打卡记录表';
|
) engine = innodb comment '打卡记录表';
|
||||||
|
|
||||||
create table goods
|
create table goods
|
||||||
(
|
(
|
||||||
|
id bigint(15) primary key auto_increment,
|
||||||
|
category tinyint(2) null default 1 comment '商品类别(1:普通 2:精选 3:秒杀 4:抽奖)',
|
||||||
|
type tinyint(2) null default 1 comment '商品类型(1:实物 2:虚拟)',
|
||||||
|
title varchar(50) not null,
|
||||||
|
origin_price int(10) unsigned comment '原价' default 0,
|
||||||
|
price int(10) unsigned not null comment '价格',
|
||||||
|
stock int(10) unsigned not null comment '库存数量',
|
||||||
|
limit_count int(10) unsigned null default 1 comment '购买最大数量(0表示不限制)',
|
||||||
|
cover varchar(200) not null comment '商品图',
|
||||||
|
description text not null comment '描述',
|
||||||
|
notice varchar(500) null comment '提示',
|
||||||
|
online_time datetime not null comment '上架时间',
|
||||||
|
offline_time datetime not null comment '下架时间',
|
||||||
|
create_time datetime default current_timestamp,
|
||||||
|
update_time datetime null on update current_timestamp,
|
||||||
|
status tinyint(2) default 1,
|
||||||
|
index ix_title (title)
|
||||||
) engine = innodb comment '商品表';
|
) engine = innodb comment '商品表';
|
||||||
|
|
||||||
|
create table order_info
|
||||||
|
(
|
||||||
|
id varchar(50) not null comment '订单编号',
|
||||||
|
gid bigint(15) not null comment '商品编号',
|
||||||
|
price int(10) not null comment '价格',
|
||||||
|
uid int(10) not null comment '用户编号',
|
||||||
|
data json null comment '订单数据',
|
||||||
|
create_time datetime default current_timestamp,
|
||||||
|
update_time datetime null on update current_timestamp,
|
||||||
|
status tinyint(2) default 1 comment '订单状态(0:已删除 1:待确认 2:已取消 3:已完成)'
|
||||||
|
) comment '订单表';
|
4
api/src/main/resources/docs/process/create_order.svg
Normal file
4
api/src/main/resources/docs/process/create_order.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.5 KiB |
1
api/src/main/resources/docs/process/创建订单.svg
Normal file
1
api/src/main/resources/docs/process/创建订单.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 18 KiB |
57
api/src/main/resources/mapper/GoodsMapper.xml
Normal file
57
api/src/main/resources/mapper/GoodsMapper.xml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="me.xiaoyan.point.api.mapper.GoodsMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="me.xiaoyan.point.api.pojo.Goods">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="category" column="category" jdbcType="TINYINT"/>
|
||||||
|
<result property="type" column="type" jdbcType="TINYINT"/>
|
||||||
|
<result property="title" column="title" jdbcType="VARCHAR"/>
|
||||||
|
<result property="originPrice" column="origin_price" jdbcType="INTEGER"/>
|
||||||
|
<result property="price" column="price" jdbcType="INTEGER"/>
|
||||||
|
<result property="stock" column="stock" jdbcType="INTEGER"/>
|
||||||
|
<result property="limitCount" column="limit_count" jdbcType="INTEGER"/>
|
||||||
|
<result property="cover" column="cover" jdbcType="VARCHAR"/>
|
||||||
|
<result property="description" column="description" jdbcType="VARCHAR"/>
|
||||||
|
<result property="notice" column="notice" jdbcType="VARCHAR"/>
|
||||||
|
<result property="onlineTime" column="online_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="offlineTime" column="offline_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="status" column="status" jdbcType="TINYINT"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,category,type,
|
||||||
|
title,origin_price,price,
|
||||||
|
stock,limit_count,cover,
|
||||||
|
description,notice,online_time,
|
||||||
|
offline_time,create_time,update_time,
|
||||||
|
status
|
||||||
|
</sql>
|
||||||
|
<update id="deductCount">
|
||||||
|
update points_sys.goods
|
||||||
|
set stock=stock - #{count}
|
||||||
|
where id = #{id}
|
||||||
|
and stock >= #{count}
|
||||||
|
</update>
|
||||||
|
<select id="queryByCategory" resultType="me.xiaoyan.point.api.pojo.Goods">
|
||||||
|
select *
|
||||||
|
from points_sys.goods
|
||||||
|
where online_time < current_timestamp
|
||||||
|
and offline_time > current_timestamp
|
||||||
|
and stock > 0
|
||||||
|
and category = #{category}
|
||||||
|
and status != 0
|
||||||
|
</select>
|
||||||
|
<select id="queryAllGoodsIdAndStock" resultType="me.xiaoyan.point.api.pojo.Goods">
|
||||||
|
select id,stock
|
||||||
|
from points_sys.goods
|
||||||
|
where online_time < current_timestamp
|
||||||
|
and offline_time > current_timestamp
|
||||||
|
and status != 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
4
api/src/main/resources/mapper/OrderInfoMapper.xml
Normal file
4
api/src/main/resources/mapper/OrderInfoMapper.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="me.xiaoyan.point.api.mapper.OrderInfoMapper">
|
||||||
|
</mapper>
|
@ -2,12 +2,42 @@ package me.xiaoyan.point.api;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class ApiApplicationTests {
|
class ApiApplicationTests {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
void contextLoads() {
|
||||||
}
|
}
|
||||||
|
void testBuy(long buyCount){
|
||||||
|
long count = stringRedisTemplate.opsForValue().decrement("a",buyCount);
|
||||||
|
System.out.println(count);
|
||||||
|
if(count<0){
|
||||||
|
System.out.println("库存不足");
|
||||||
|
stringRedisTemplate.opsForValue().increment("a",buyCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(count == 0){
|
||||||
|
System.out.println("下一次就没有存库了");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("购买成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRedis(){
|
||||||
|
stringRedisTemplate.opsForValue().set("a","1");
|
||||||
|
System.out.println("----------第1次----------");
|
||||||
|
testBuy(2);
|
||||||
|
System.out.println("----------第2次----------");
|
||||||
|
testBuy(1);
|
||||||
|
System.out.println("----------第3次----------");
|
||||||
|
testBuy(1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user