清理已迁移的 cart 代码

This commit is contained in:
YunaiV 2022-09-12 10:00:17 +08:00
parent a347d2a1d3
commit 239c38cf64
113 changed files with 0 additions and 5310 deletions

View File

@ -1,28 +0,0 @@
package cn.iocoder.mall.managementweb.convert.promotion;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerCreateReqVO;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerPageReqVO;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerRespVO;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerUpdateReqVO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerCreateReqDTO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerPageReqDTO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerRespDTO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerUpdateReqDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface BannerConvert {
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
BannerCreateReqDTO convert(BannerCreateReqVO bean);
BannerUpdateReqDTO convert(BannerUpdateReqVO bean);
BannerPageReqDTO convert(BannerPageReqVO bean);
PageResult<BannerRespVO> convertPage(PageResult<BannerRespDTO> page);
}

View File

@ -1,68 +0,0 @@
package cn.iocoder.mall.managementweb.manager.promotion.brand;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerCreateReqVO;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerPageReqVO;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerRespVO;
import cn.iocoder.mall.managementweb.controller.promotion.brand.vo.BannerUpdateReqVO;
import cn.iocoder.mall.managementweb.convert.promotion.BannerConvert;
import cn.iocoder.mall.promotion.api.rpc.banner.BannerFeign;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerRespDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Banner Manager
*/
@Service
public class BannerManager {
@Autowired
private BannerFeign bannerFeign;
/**
* 创建 Banner
*
* @param createVO 创建 Banner VO
* @return Banner
*/
public Integer createBanner(BannerCreateReqVO createVO) {
CommonResult<Integer> createBannerResult = bannerFeign.createBanner(BannerConvert.INSTANCE.convert(createVO));
createBannerResult.checkError();
return createBannerResult.getData();
}
/**
* 更新 Banner
*
* @param updateVO 更新 Banner VO
*/
public void updateBanner(BannerUpdateReqVO updateVO) {
CommonResult<Boolean> updateBannerResult = bannerFeign.updateBanner(BannerConvert.INSTANCE.convert(updateVO));
updateBannerResult.checkError();
}
/**
* 删除 Banner
*
* @param bannerId Banner 编号
*/
public void deleteBanner(Integer bannerId) {
CommonResult<Boolean> deleteBannerResult = bannerFeign.deleteBanner(bannerId);
deleteBannerResult.checkError();
}
/**
* 获得 Banner 分页
*
* @param pageVO Banner 分页查询
* @return Banner 分页结果
*/
public PageResult<BannerRespVO> pageBanner(BannerPageReqVO pageVO) {
CommonResult<PageResult<BannerRespDTO>> pageBannerResult = bannerFeign.pageBanner(BannerConvert.INSTANCE.convert(pageVO));
pageBannerResult.checkError();
return BannerConvert.INSTANCE.convertPage(pageBannerResult.getData());
}
}

View File

@ -1,21 +0,0 @@
## 订单
TODO
**退货**
1. 商家未发货,退货原因
- 拍错/勿拍/多拍
- 缺货
2. 商家已发货,退货原因
- 七天无理由
- 质量问题
- 不想要了
- 其他

View File

@ -1,129 +0,0 @@
<?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="cn.iocoder.mall.order.biz.dao.cart.CartMapper">
<sql id="FIELDS">
id, status, delete_time, selected, user_id,
spu_id, sku_id, quantity, order_id, order_create_time,
create_time
</sql>
<select id="selectById" parameterType="Integer" resultType="CartItemDO">
SELECT
<include refid="FIELDS" />
FROM cart_item
WHERE id = #{id}
-- AND deleted = 0
</select>
<select id="selectByIds" resultType="CartItemDO">
SELECT
<include refid="FIELDS" />
FROM cart_item
WHERE id IN
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
#{id}
</foreach>
-- AND deleted = 0
</select>
<select id="selectByUserIdAndSkuIdAndStatus" resultType="CartItemDO">
SELECT
<include refid="FIELDS" />
FROM cart_item
WHERE user_id = #{userId}
AND sku_id = #{skuId}
AND status = #{status}
-- AND deleted = 0
LIMIT 1
</select>
<select id="selectByUserIdAndStatusAndSelected" resultType="CartItemDO">
SELECT
<include refid="FIELDS" />
FROM cart_item
WHERE user_id = #{userId}
AND status = #{status}
<if test="selected != null">
AND selected = #{selected}
</if>
-- AND deleted = 0
</select>
<select id="selectQuantitySumByUserIdAndStatus" resultType="Integer">
SELECT
SUM(quantity)
FROM cart_item
WHERE user_id = #{userId}
AND status = #{status}
-- AND deleted = 0
</select>
<insert id="insert" parameterType="CartItemDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO cart_item (
status, delete_time, selected, user_id,
spu_id, sku_id, quantity, order_id, order_create_time,
create_time
) VALUES (
#{status}, #{deleteTime}, #{selected}, #{userId},
#{spuId}, #{skuId}, #{quantity}, #{orderId}, #{orderCreateTime},
#{createTime}
)
</insert>
<update id="update" parameterType="CartItemDO">
UPDATE cart_item
<set>
<if test="status != null">
status = #{status},
</if>
<if test="deleteTime != null">
delete_time = #{deleteTime},
</if>
<if test="selected != null">
selected = #{selected},
</if>
<if test="quantity != null">
quantity = #{quantity},
</if>
<if test="orderId != null">
order_id = #{orderId},
</if>
<if test="orderCreateTime != null">
order_create_time = #{orderCreateTime},
</if>
<if test="price != null">
price = #{price},
</if>
<if test="quantity != null">
quantity = #{quantity},
</if>
</set>
WHERE id = #{id}
</update>
<update id="updateQuantity" parameterType="CartItemDO">
UPDATE cart_item
SET quantity = quantity + #{quantityIncr}
WHERE id = #{id}
</update>
<update id="updateListByUserIdAndSkuId">
UPDATE cart_item
<set>
<if test="selected != null">
selected = #{selected},
</if>
<if test="status != null">
status = #{status},
</if>
</set>
WHERE user_id = #{userId}
AND sku_id IN
<foreach item="skuId" collection="skuIds" separator="," open="(" close=")" index="">
#{skuId}
</foreach>
-- AND deleted = 0
</update>
</mapper>

View File

@ -1,64 +0,0 @@
package cn.iocoder.mall.productservice.dal.mysql.dataobject.sku;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
import cn.iocoder.mall.productservice.dal.mysql.dataobject.attr.ProductAttrValueDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 商品 SKU
*/
@TableName("product_sku")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class ProductSkuDO extends DeletableDO {
/**
* sku 编号
*/
private Integer id;
/**
* 商品编号
*/
private Integer spuId;
// TODO 店铺编号
/**
* 状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 图片地址
*/
private String picUrl;
/**
* 规格值({@link ProductAttrValueDO#getId()})数组
*
* 数组以逗号分隔
*/
private String attrs;
/**
* 价格单位
*/
private Integer price;
/**
* 库存数量
*/
private Integer quantity;
// /**
// * 商品在付款减库存的状态下该Sku上未付款的订单数量
// */
// private Integer withHoldQuantity;
// /**
// * 销量
// */
// private Integer soldNum;
}

View File

@ -1,82 +0,0 @@
package cn.iocoder.mall.productservice.dal.mysql.dataobject.spu;
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 商品 SPU
*
* TODO 芋艿后面增加商品普通参数例如说正面材料背面材料屏幕尺寸
*/
@TableName("product_spu")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class ProductSpuDO extends DeletableDO {
/**
* SPU 编号
*/
private Integer id;
// TODO 店铺编号 先不考虑因为第一个版本不做 B2B2C
// ========== 基本信息 =========
/**
* SPU 名字
*/
private String name;
/**
* 卖点
*/
private String sellPoint;
/**
* 描述
*/
private String description;
/**
* 分类编号
*/
private Integer cid;
/**
* 商品主图地址
*
* 数组以逗号分隔
*
* 建议尺寸800*800像素你可以拖拽图片调整顺序最多上传15张
*/
private String picUrls;
// TODO 运费信息
// ========== 其他信息 =========
/**
* 是否上架商品是否可见
*
* true 为已上架
* false 为已下架
*/
private Boolean visible;
/**
* 排序字段
*/
private Integer sort;
// ========== Sku 相关字段 =========
/**
* 价格
*
* 目前的计算方式是 Sku 最小价格为准
*/
private Integer price;
/**
* 库存数量
*
* 目前的计算方式是 Sku 库存累加为准
*/
private Integer quantity;
}

View File

@ -17,8 +17,6 @@ public interface ProductSkuMapper extends BaseMapper<ProductSkuDO> {
.eq("status", status));
}
void insertList(@Param("productSkuDOs") List<ProductSkuDO> productSkuDOs);
default List<ProductSkuDO> selectList(ProductSkuListQueryBO queryBO) {
return selectList(new QueryWrapperX<ProductSkuDO>().eqIfPresent("id", queryBO.getProductSkuId())
.inIfPresent("id", queryBO.getProductSkuIds())

View File

@ -32,17 +32,6 @@ public class ProductSkuManager {
@Autowired
private ProductAttrService productAttrService;
/**
* 获得商品 SKU
*
* @param productSkuId 商品 SKU编号
* @return 商品 SKU
*/
public ProductSkuRespDTO getProductSku(Integer productSkuId) {
ProductSkuBO productSkuBO = productSkuService.getProductSku(productSkuId);
return ProductSkuConvert.INSTANCE.convert(productSkuBO);
}
/**
* 获得商品 SKU 列表
*

View File

@ -51,17 +51,6 @@ public class ProductSpuManager {
@Autowired
private ProductMQProducer productMQProducer;
/**
* 获得商品 SPU
*
* @param productSpuId 商品 SPU编号
* @return 商品 SPU
*/
public ProductSpuRespDTO getProductSpu(Integer productSpuId) {
ProductSpuBO productSpuBO = productSpuService.getProductSpu(productSpuId);
return ProductSpuConvert.INSTANCE.convert(productSpuBO);
}
/**
* 获得商品 SPU列表
*
@ -84,25 +73,6 @@ public class ProductSpuManager {
return ProductSpuConvert.INSTANCE.convertPage(pageResultBO);
}
/**
* 添加或修改商品 SPU 校验商品分类是否合法
*
* @param cid 商品分类编号
* @return 商品分类
*/
private ProductCategoryBO checkProductCategory(Integer cid) {
ProductCategoryBO categoryBO = productCategoryService.getProductCategory(cid);
if (categoryBO == null) {
// 不存在
throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_NOT_EXISTS);
}
if (ProductCategoryIdEnum.ROOT.getId().equals(categoryBO.getPid())) {
// 商品只能添加到二级分类下
throw ServiceExceptionUtil.exception(PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2);
}
return categoryBO;
}
/**
* 顺序获得商品 SPU 编号数组
*

View File

@ -22,15 +22,6 @@ public class ProductSkuService {
@Autowired
private ProductSkuMapper productSkuMapper;
public void createProductSkus(Integer spuId, List<ProductSkuCreateOrUpdateBO> createSkuBOs) {
List<ProductSkuDO> skus = ProductSkuConvert.INSTANCE.convertList(createSkuBOs);
skus.forEach(sku -> {
sku.setStatus(CommonStatusEnum.ENABLE.getValue());
sku.setSpuId(spuId);
});
productSkuMapper.insertList(skus);
}
/**
* 获得 sku 数组中指定规格的 sku
*
@ -54,17 +45,6 @@ public class ProductSkuService {
return null;
}
/**
* 获得商品 SKU
*
* @param productSkuId 商品 SKU 编号
* @return 商品 SKU
*/
public ProductSkuBO getProductSku(Integer productSkuId) {
ProductSkuDO productSkuDO = productSkuMapper.selectById(productSkuId);
return ProductSkuConvert.INSTANCE.convert(productSkuDO);
}
/**
* 获得商品 SKU 列表
*

View File

@ -1,60 +0,0 @@
package cn.iocoder.mall.productservice.service.sku.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
/**
* 商品 SKU BO
*/
@Data
@Accessors(chain = true)
public class ProductSkuBO {
/**
* sku 编号
*/
private Integer id;
/**
* 商品编号
*/
private Integer spuId;
/**
* 状态
*
* 1-正常
* 2-禁用
*/
private Integer status;
/**
* 图片地址
*/
private String picUrl;
/**
* 规格值编号数组
*/
private List<Integer> attrValueIds;
/**
* 价格单位
*/
private Integer price;
/**
* 库存数量
*/
private Integer quantity;
/**
* 创建时间
*/
private Date createTime;
/**
* 最后更新时间
*/
private Date updateTime;
/**
* 是否删除
*/
private Integer deleted;
}

View File

@ -1,61 +0,0 @@
package cn.iocoder.mall.productservice.service.spu.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
import java.util.List;
/**
* 商品 SPU 信息 BO
*/
@Data
@Accessors(chain = true)
public class ProductSpuBO {
/**
* 商品 SPU 编号
*/
private Integer id;
/**
* SPU 名字
*/
private String name;
/**
* 卖点
*/
private String sellPoint;
/**
* 描述
*/
private String description;
/**
* 分类编号
*/
private Integer cid;
/**
* 商品主图地址
*/
private List<String> picUrls;
/**
* 是否上架商品
*/
private Boolean visible;
/**
* 排序字段
*/
private Integer sort;
/**
* 价格
*/
private Integer price;
/**
* 库存数量
*/
private Integer quantity;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -1,63 +0,0 @@
package cn.iocoder.mall.productservice.service.spu.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 商品 SPU 创建 BO
*/
@Data
@Accessors(chain = true)
public class ProductSpuCreateBO {
/**
* SPU 名字
*/
@NotEmpty(message = "SPU 名字不能为空")
private String name;
/**
* 卖点
*/
@NotEmpty(message = "卖点不能为空")
private String sellPoint;
/**
* 描述
*/
@NotEmpty(message = "描述不能为空")
private String description;
/**
* 分类编号
*/
@NotNull(message = "分类编号不能为空")
private Integer cid;
/**
* 商品主图地址
*/
@NotEmpty(message = "商品主图地址不能为空")
private List<String> picUrls;
/**
* 是否上架商品
*/
@NotNull(message = "是否上架商品不能为空")
private Boolean visible;
/**
* 排序字段
*/
@NotNull(message = "排序字段不能为空")
private Integer sort;
/**
* 价格
*/
@NotNull(message = "价格不能为空")
private Integer price;
/**
* 库存数量
*/
@NotNull(message = "库存数量不能为空")
private Integer quantity;
}

View File

@ -1,67 +0,0 @@
package cn.iocoder.mall.productservice.service.spu.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 商品 SPU 更新 BO
*/
@Data
@Accessors(chain = true)
public class ProductSpuUpdateBO {
/**
* 商品 SPU 编号
*/
@NotNull(message = "商品 SPU 编号不能为空")
private Integer id;
/**
* SPU 名字
*/
@NotEmpty(message = "SPU 名字不能为空")
private String name;
/**
* 卖点
*/
@NotEmpty(message = "卖点不能为空")
private String sellPoint;
/**
* 描述
*/
@NotEmpty(message = "描述不能为空")
private String description;
/**
* 分类编号
*/
@NotNull(message = "分类编号不能为空")
private Integer cid;
/**
* 商品主图地址
*/
@NotEmpty(message = "商品主图地址不能为空")
private List<String> picUrls;
/**
* 是否上架商品
*/
@NotNull(message = "是否上架商品不能为空")
private Boolean visible;
/**
* 排序字段
*/
private Integer sort;
/**
* 价格
*/
@NotNull(message = "价格不能为空")
private Integer price;
/**
* 库存数量
*/
@NotNull(message = "库存数量不能为空")
private Integer quantity;
}

View File

@ -1,35 +0,0 @@
package cn.iocoder.mall.promotion.api.rpc.banner;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* Title:
* Description:
*
* @author zhuyang
* @version 1.0 2021/10/9
*/
@FeignClient("promotion-service")
public interface BannerFeign {
@PostMapping("/promotion/banner/createBanner")
public CommonResult<Integer> createBanner(@RequestBody BannerCreateReqDTO createDTO) ;
@PostMapping("/promotion/banner/updateBanner")
public CommonResult<Boolean> updateBanner(@RequestBody BannerUpdateReqDTO updateDTO) ;
@PostMapping("/promotion/banner/deleteBanner")
public CommonResult<Boolean> deleteBanner(@RequestBody Integer bannerId) ;
@PostMapping("/promotion/banner/listBanners")
public CommonResult<List<BannerRespDTO>> listBanners(@RequestBody BannerListReqDTO listDTO) ;
@PostMapping("/promotion/banner/pageBanner")
public CommonResult<PageResult<BannerRespDTO>> pageBanner(@RequestBody BannerPageReqDTO pageDTO);
}

View File

@ -1,58 +0,0 @@
package cn.iocoder.mall.promotion.api.rpc.banner.dto;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* Banner 创建 Request DTO
*/
@Data
@Accessors(chain = true)
public class BannerCreateReqDTO implements Serializable {
/**
* 标题
*/
@NotEmpty(message = "标题不能为空")
@Length(min = 2, max = 32, message = "标题长度为 2-32 位")
private String title;
/**
* 跳转链接
*/
@NotEmpty(message = "跳转链接不能为空")
@URL(message = "跳转链接格式不正确")
@Length(max = 255, message = "跳转链接最大长度为 255 位")
private String url;
/**
* 图片链接
*/
@NotEmpty(message = "图片链接不能为空")
@URL(message = "图片链接格式不正确")
@Length(max = 255, message = "图片链接最大长度为 255 位")
private String picUrl;
/**
* 排序
*/
@NotNull(message = "排序不能为空")
private Integer sort;
/**
* 状态
*/
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
/**
* 备注
*/
@Length(max = 255, message = "备注最大长度为 255 位")
private String memo;
}

View File

@ -1,23 +0,0 @@
package cn.iocoder.mall.promotion.api.rpc.banner.dto;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* Banner 列表 Request DTO
*/
@Data
@Accessors(chain = true)
public class BannerListReqDTO implements Serializable {
/**
* 状态
*/
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
}

View File

@ -1,21 +0,0 @@
package cn.iocoder.mall.promotion.api.rpc.banner.dto;
import cn.iocoder.common.framework.vo.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* Banner 分页 Request DTO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class BannerPageReqDTO extends PageParam {
/**
* 标题模糊匹配
*/
private String title;
}

View File

@ -1,49 +0,0 @@
package cn.iocoder.mall.promotion.api.rpc.banner.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* Banner Response DTO
*/
@Data
@Accessors(chain = true)
public class BannerRespDTO implements Serializable {
/**
* 编号
*/
private Integer id;
/**
* 标题
*/
private String title;
/**
* 跳转链接
*/
private String url;
/**
* 图片链接
*/
private String picUrl;
/**
* 排序
*/
private Integer sort;
/**
* 状态
*/
private Integer status;
/**
* 备注
*/
private String memo;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -1,63 +0,0 @@
package cn.iocoder.mall.promotion.api.rpc.banner.dto;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* Banner 更新 Request DTO
*/
@Data
@Accessors(chain = true)
public class BannerUpdateReqDTO implements Serializable {
/**
* 编号
*/
@NotNull(message = "编号不能为空")
private Integer id;
/**
* 标题
*/
@NotEmpty(message = "标题不能为空")
@Length(min = 2, max = 32, message = "标题长度为 2-32 位")
private String title;
/**
* 跳转链接
*/
@NotEmpty(message = "跳转链接不能为空")
@URL(message = "跳转链接格式不正确")
@Length(max = 255, message = "跳转链接最大长度为 255 位")
private String url;
/**
* 图片链接
*/
@NotEmpty(message = "图片链接不能为空")
@URL(message = "图片链接格式不正确")
@Length(max = 255, message = "图片链接最大长度为 255 位")
private String picUrl;
/**
* 排序
*/
@NotNull(message = "排序不能为空")
private Integer sort;
/**
* 状态
*/
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
/**
* 备注
*/
@Length(max = 255, message = "备注最大长度为 255 位")
private String memo;
}

View File

@ -1,57 +0,0 @@
package cn.iocoder.mall.promotionservice.controller;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.*;
import cn.iocoder.mall.promotionservice.manager.banner.BannerManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.success;
/**
* Title:
* Description:
*
* @author zhuyang
* @version 1.0 2021/10/9
*/
@RestController
@RequestMapping("/promotion/banner")
public class BannerController {
@Autowired
private BannerManager bannerManager;
@PostMapping("createBanner")
public CommonResult<Integer> createBanner(@RequestBody BannerCreateReqDTO createDTO) {
return success(bannerManager.createBanner(createDTO));
}
@PostMapping("updateBanner")
public CommonResult<Boolean> updateBanner(@RequestBody BannerUpdateReqDTO updateDTO) {
bannerManager.updateBanner(updateDTO);
return success(true);
}
@PostMapping("deleteBanner")
public CommonResult<Boolean> deleteBanner(@RequestBody Integer bannerId) {
bannerManager.deleteBanner(bannerId);
return success(true);
}
@PostMapping("listBanners")
public CommonResult<List<BannerRespDTO>> listBanners(@RequestBody BannerListReqDTO listDTO) {
return success(bannerManager.listBanners(listDTO));
}
@PostMapping("pageBanner")
public CommonResult<PageResult<BannerRespDTO>> pageBanner(@RequestBody BannerPageReqDTO pageDTO) {
return success(bannerManager.pageBanner(pageDTO));
}
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.mall.promotionservice.convert.banner;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerCreateReqDTO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerRespDTO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerUpdateReqDTO;
import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.banner.BannerDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface BannerConvert {
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
BannerDO convert(BannerCreateReqDTO bean);
BannerDO convert(BannerUpdateReqDTO bean);
@Mapping(source = "records", target = "list")
PageResult<BannerRespDTO> convertPage(IPage<BannerDO> page);
List<BannerRespDTO> convertList(List<BannerDO> list);
}

View File

@ -1,42 +0,0 @@
package cn.iocoder.mall.promotionservice.manager.banner;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.*;
import cn.iocoder.mall.promotionservice.service.banner.BannerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.validation.Valid;
import java.util.List;
/**
* Banner Manager
*/
@Service
@Valid
public class BannerManager {
@Autowired
private BannerService bannerService;
public Integer createBanner(BannerCreateReqDTO createDTO) {
return bannerService.createBanner(createDTO);
}
public void updateBanner(BannerUpdateReqDTO updateDTO) {
bannerService.updateBanner(updateDTO);
}
public void deleteBanner(Integer bannerId) {
bannerService.deleteBanner(bannerId);
}
public List<BannerRespDTO> listBanners(BannerListReqDTO listDTO) {
return bannerService.listBanners(listDTO);
}
public PageResult<BannerRespDTO> pageBanner(BannerPageReqDTO pageDTO) {
return bannerService.pageBanner(pageDTO);
}
}

View File

@ -1,137 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>onemall</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-web-app</artifactId>
<description>商城,用于用户购物</description>
<dependencyManagement>
<dependencies>
<!-- onemall 基础 bom 文件 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-swagger</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-security-user</artifactId>
</dependency>
<!-- RPC 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-dubbo</artifactId>
</dependency>
<dependency>
<!-- 用户服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 商品服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>product-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 搜索服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>search-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 订单服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>trade-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 营销服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>promotion-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 系统服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 支付服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>pay-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Registry 和 Config 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<!-- 使用 spring-boot-maven-plugin 插件打包 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,19 +0,0 @@
package cn.iocoder.mall.shopweb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"cn.iocoder.mall.productservice.rpc","cn.iocoder.mall.searchservice.rpc",
"cn.iocoder.mall.tradeservice.rpc","cn.iocoder.mall.payservice.rpc","cn.iocoder.mall.promotion.api.rpc",
"cn.iocoder.mall.systemservice.rpc","cn.iocoder.mall.userservice.rpc"})
public class ShopWebApplication {
public static void main(String[] args) {
SpringApplication.run(ShopWebApplication.class, args);
}
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.mall.shopweb.client.user;
import cn.iocoder.mall.userservice.rpc.address.UserAddressFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserAddressClient {
@Autowired
private UserAddressFeign userAddressFeign;
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.mall.shopweb.controller.product.vo.category;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel("商品分类 Response VO")
@Data
public class ProductCategoryRespVO {
@ApiModelProperty(value = "分类编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "分类名称", required = true, example = "手机")
private String name;
@ApiModelProperty(value = "分类图片", notes = "一般情况下,只有根分类才有图片", example = "http://www.iocoder.cn/xx.jpg")
private String picUrl;
}

View File

@ -1,61 +0,0 @@
package cn.iocoder.mall.shopweb.controller.product.vo.product;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@ApiModel("商品 SPU Response VO")
@Data
@Accessors(chain = true)
public class ProductSpuRespVO {
@ApiModelProperty(value = "SPU 编号", required = true, example = "1")
private Integer id;
// ========== 基本信息 =========
@ApiModelProperty(value = "SPU 名字", required = true, example = "芋艿")
private String name;
@ApiModelProperty(value = "卖点", required = true, example = "好吃好玩")
private String sellPoint;
@ApiModelProperty(value = "描述", required = true, example = "我是哈哈哈")
private String description;
@ApiModelProperty(value = "分类编号", required = true, example = "1")
private Integer cid;
@ApiModelProperty(value = "分类名字", required = true, example = "蔬菜")
private String categoryName;
@ApiModelProperty(value = "商品主图地址", required = true, example = "http://www.iocoder.cn/xxx.jpg", notes = "多个之间,使用逗号分隔")
private List<String> picUrls;
// ========== 其他信息 =========
@ApiModelProperty(value = "是否上架商品", required = true, example = "true")
private Boolean visible;
@ApiModelProperty(value = "排序字段", required = true, example = "1024")
private Integer sort;
// ========== Sku 相关字段 =========
@ApiModelProperty(value = "原始价格,单位:分", required = true, example = "233", notes = "该价格为商品的原始价格")
private Integer originalPrice;
@ApiModelProperty(value = "购买价格,单位:分", required = true, example = "233", notes = "该价格为商品经过优惠计算后的价格")
private Integer buyPrice;
@ApiModelProperty(value = "库存数量", required = true, example = "1024")
private Integer quantity;
// ========== 促销活动相关字段 ========= TODO 芋艿等做到促销在处理
// 目前只促销单体商品促销目前仅限制折扣
/**
* 促销活动编号
*/
private Integer promotionActivityId;
/**
* 促销活动标题
*/
private String promotionActivityTitle;
/**
* 促销活动类型
*/
private Integer promotionActivityType;
}

View File

@ -1,19 +0,0 @@
### /passport/login-by-sms 成功
POST {{shop-api-base-url}}/passport/login-by-sms
Content-Type: application/x-www-form-urlencoded
mobile=15601691300&code=9999
### /passport/send-sms-code 成功
POST {{shop-api-base-url}}/passport/send-sms-code
Content-Type: application/x-www-form-urlencoded
mobile=15601691300&scene=1
### /passport/refresh-token
POST {{shop-api-base-url}}/passport/refresh-token
Content-Type: application/x-www-form-urlencoded
refreshToken=77abd74e84e34cfc8aba9625317a14a3
###

View File

@ -1,56 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user;
import cn.iocoder.common.framework.util.HttpUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportAccessTokenRespVO;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportLoginBySmsReqVO;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportSendSmsRespVO;
import cn.iocoder.mall.shopweb.service.user.PassportManager;
import cn.iocoder.security.annotations.RequiresNone;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@Api(tags = "用户 Passport API")
@RestController
@RequestMapping("/passport")
public class PassportController {
@Autowired
private PassportManager passportManager;
@PostMapping("/login-by-sms")
@ApiOperation("手机验证码登陆")
@RequiresNone
public CommonResult<PassportAccessTokenRespVO> loginBySms(PassportLoginBySmsReqVO loginBySmsDTO,
HttpServletRequest request) {
return success(passportManager.loginBySms(loginBySmsDTO, HttpUtil.getIp(request)));
}
@PostMapping("/send-sms-code")
@ApiOperation("发送手机验证码")
@RequiresNone
public CommonResult<Boolean> sendSmsCode(PassportSendSmsRespVO sendSmsCodeDTO,
HttpServletRequest request) {
passportManager.sendSmsCode(sendSmsCodeDTO, HttpUtil.getIp(request));
// 返回成功
return success(true);
}
@PostMapping("/refresh-token")
@ApiOperation("刷新令牌")
@RequiresNone
public CommonResult<PassportAccessTokenRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken,
HttpServletRequest request) {
return success(passportManager.refreshToken(refreshToken, HttpUtil.getIp(request)));
}
}

View File

@ -1,6 +0,0 @@
### /user-address/get-default 成功
GET {{shop-api-base-url}}/user-address/get-default
Authorization: Bearer {{user-access-token}}
dubbo-tag: {{dubboTag}}
###

View File

@ -1,80 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressCreateReqVO;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressRespVO;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressUpdateReqVO;
import cn.iocoder.mall.shopweb.service.user.UserAddressManager;
import cn.iocoder.security.annotations.RequiresPermissions;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.success;
/**
* 用户收件地址 Controller
*/
@RestController
@RequestMapping("/user-address")
@Api(tags = "用户收件地址")
@Validated
public class UserAddressController {
@Autowired
private UserAddressManager userAddressManager;
@PostMapping("/create")
@ApiOperation("创建用户收件地址")
@RequiresPermissions
public CommonResult<Integer> createUserAddress(@Valid UserAddressCreateReqVO createVO) {
return success(userAddressManager.createUserAddress(UserSecurityContextHolder.getUserId(), createVO));
}
@PostMapping("/update")
@ApiOperation("更新用户收件地址")
@RequiresPermissions
public CommonResult<Boolean> updateUserAddress(@Valid UserAddressUpdateReqVO updateVO) {
userAddressManager.updateUserAddress(UserSecurityContextHolder.getUserId(), updateVO);
return success(true);
}
@PostMapping("/delete")
@ApiOperation("删除用户收件地址")
@ApiImplicitParam(name = "userAddressId", value = "用户收件地址编号", required = true)
@RequiresPermissions
public CommonResult<Boolean> deleteUserAddress(@RequestParam("userAddressId") Integer userAddressId) {
userAddressManager.deleteUserAddress(UserSecurityContextHolder.getUserId(), userAddressId);
return success(true);
}
@GetMapping("/get")
@ApiOperation("获得用户收件地址")
@ApiImplicitParam(name = "userAddressId", value = "用户收件地址编号", required = true)
@RequiresPermissions
public CommonResult<UserAddressRespVO> getUserAddress(@RequestParam("userAddressId") Integer userAddressId) {
return success(userAddressManager.getUserAddress(UserSecurityContextHolder.getUserId(), userAddressId));
}
@GetMapping("/get-default")
@ApiOperation("获得默认的用户收件地址")
@RequiresPermissions
public CommonResult<UserAddressRespVO> getDefaultUserAddress() {
return success(userAddressManager.getDefaultUserAddress(UserSecurityContextHolder.getUserId()));
}
@GetMapping("/list")
@ApiOperation("获得用户收件地址列表")
@RequiresPermissions
public CommonResult<List<UserAddressRespVO>> listUserAddresses() {
return success(userAddressManager.listUserAddresses(UserSecurityContextHolder.getUserId()));
}
}

View File

@ -1,50 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
import cn.iocoder.mall.shopweb.controller.user.vo.user.UserRespVO;
import cn.iocoder.mall.shopweb.service.user.UserManager;
import cn.iocoder.security.annotations.RequiresAuthenticate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@Api(tags = "用户信息 API")
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserManager userManager;
@ApiOperation(value = "用户信息")
@GetMapping("/info")
@RequiresAuthenticate
public CommonResult<UserRespVO> getUserInfo() {
UserRespVO user = userManager.getUser(UserSecurityContextHolder.getUserId());
return success(user);
}
@PostMapping("/update-avatar")
@RequiresAuthenticate
@ApiOperation(value = "更新头像")
@ApiImplicitParam(name = "avatar", value = "头像", required = true, example = "http://www.iocoder.cn/xxx.png")
public CommonResult<Boolean> updateUserAvatar(@RequestParam("avatar") String avatar) {
userManager.updateUserAvatar(UserSecurityContextHolder.getUserId(), avatar);
return success(true);
}
@PostMapping("/update-nickname")
@RequiresAuthenticate
@ApiOperation(value = "更新昵称")
@ApiImplicitParam(name = "nickname", value = "昵称", required = true, example = "蠢艿艿")
public CommonResult<Boolean> updateUserNickname(@RequestParam("nickname") String nickname) {
userManager.updateUserNickname(UserSecurityContextHolder.getUserId(), nickname);
return success(true);
}
}

View File

@ -1,33 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.address;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.userservice.enums.address.UserAddressType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ApiModel("用户收件地址创建 Request VO")
@Data
public class UserAddressCreateReqVO {
@ApiModelProperty(value = "收件人名称", required = true, example = "帅艿艿")
@NotEmpty(message = "收件人名称不能为空")
private String name;
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
@NotEmpty(message = "手机号不能为空")
private String mobile;
@ApiModelProperty(value = "区域编号", required = true, example = "610632")
@NotNull(message = "地区编码不能为空")
private Integer areaCode;
@ApiModelProperty(value = "收件详细地址", required = true, example = "芋道源码 233 号 666 室")
@NotEmpty(message = "收件详细地址不能为空")
private String detailAddress;
@ApiModelProperty(value = "地址类型", required = true, example = "1", notes = "参见 UserAddressType 枚举类")
@NotNull(message = "地址类型不能为空")
@InEnum(value = UserAddressType.class, message = "地址类型必须是 {value}")
private Integer type;
}

View File

@ -1,31 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.address;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@ApiModel("用户收件地址 Response VO")
@Data
public class UserAddressRespVO {
@ApiModelProperty(value = "收件地址编号", required = true, example = "1024")
private Integer id;
@ApiModelProperty(value = "用户编号", required = true, example = "2048")
private Integer userId;
@ApiModelProperty(value = "收件人名称", required = true, example = "帅艿艿")
private String name;
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
private String mobile;
@ApiModelProperty(value = "区域编号", required = true, example = "610632")
private Integer areaCode;
@ApiModelProperty(value = "收件详细地址", required = true, example = "芋道源码 233 号 666 室")
private String detailAddress;
@ApiModelProperty(value = "地址类型", required = true, example = "1", notes = "参见 UserAddressType 枚举类")
private Integer type;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
}

View File

@ -1,36 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.address;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.mall.userservice.enums.address.UserAddressType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ApiModel("用户收件地址更新 Request VO")
@Data
public class UserAddressUpdateReqVO {
@ApiModelProperty(value = "收件地址编号", required = true, example = "1024")
@NotNull(message = "收件地址编号不能为空")
private Integer id;
@ApiModelProperty(value = "收件人名称", required = true, example = "帅艿艿")
@NotEmpty(message = "收件人名称不能为空")
private String name;
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
@NotEmpty(message = "手机号不能为空")
private String mobile;
@ApiModelProperty(value = "区域编号", required = true, example = "610632")
@NotNull(message = "地区编码不能为空")
private Integer areaCode;
@ApiModelProperty(value = "收件详细地址", required = true, example = "芋道源码 233 号 666 室")
@NotEmpty(message = "收件详细地址不能为空")
private String detailAddress;
@ApiModelProperty(value = "地址类型", required = true, example = "1", notes = "参见 UserAddressType 枚举类")
@NotNull(message = "地址类型不能为空")
@InEnum(value = UserAddressType.class, message = "地址类型必须是 {value}")
private Integer type;
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.passport;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
@ApiModel("访问令牌信息 Response VO")
@Data
@Accessors(chain = true)
public class PassportAccessTokenRespVO {
@ApiModelProperty(value = "访问令牌", required = true, example = "001e8f49b20e47f7b3a2de774497cd50")
private String accessToken;
@ApiModelProperty(value = "刷新令牌", required = true, example = "001e8f49b20e47f7b3a2de774497cd50")
private String refreshToken;
@ApiModelProperty(value = "过期时间", required = true)
private Date expiresTime;
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.passport;
import cn.iocoder.common.framework.validator.Mobile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
@ApiModel("用户短信验证码登陆 Request VO")
@Data
@Accessors(chain = true)
public class PassportLoginBySmsReqVO implements Serializable {
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
@NotEmpty(message = "手机号不能为空")
@Mobile
private String mobile;
@ApiModelProperty(value = "手机验证码", required = true, example = "1024")
@NotEmpty(message = "手机验证码不能为空")
@Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
private String code;
}

View File

@ -1,23 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.passport;
import cn.iocoder.common.framework.validator.Mobile;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
@ApiModel("发送手机验证码 Response VO")
@Data
@Accessors(chain = true)
public class PassportSendSmsRespVO {
@ApiModelProperty(value = "手机号", example = "15601691234")
@Mobile
private String mobile;
@ApiModelProperty(value = "发送场景", example = "1", notes = "对应 UserSmsSceneEnum 枚举")
@NotNull(message = "发送场景不能为空")
private Integer scene;
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.mall.shopweb.controller.user.vo.user;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
@ApiModel("用户信息 VO")
@Data
@Accessors(chain = true)
public class UserRespVO {
@ApiModelProperty(value = "用户编号", required = true, example = "123")
private Integer id;
@ApiModelProperty(value = "手机号", required = true, example = "15601691300")
private String mobile;
@ApiModelProperty(value = "昵称", required = true, example = "小王")
private String nickname;
@ApiModelProperty(value = "头像", required = true, example = "http://www.iocoder.cn/xxx.jpg")
private String avatar;
}

View File

@ -1,17 +0,0 @@
package cn.iocoder.mall.shopweb.convert.product;
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryRespDTO;
import cn.iocoder.mall.shopweb.controller.product.vo.category.ProductCategoryRespVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface ProductCategoryConvert {
ProductCategoryConvert INSTANCE = Mappers.getMapper(ProductCategoryConvert.class);
List<ProductCategoryRespVO> convertList(List<ProductCategoryRespDTO> list);
}

View File

@ -1,17 +0,0 @@
package cn.iocoder.mall.shopweb.convert.promotion;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerRespDTO;
import cn.iocoder.mall.shopweb.controller.promotion.vo.brand.BannerRespVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface BannerConvert {
BannerConvert INSTANCE = Mappers.getMapper(BannerConvert.class);
List<BannerRespVO> convertList(List<BannerRespDTO> list);
}

View File

@ -1,25 +0,0 @@
package cn.iocoder.mall.shopweb.convert.user;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportAccessTokenRespVO;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportLoginBySmsReqVO;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportSendSmsRespVO;
import cn.iocoder.mall.systemservice.rpc.oauth.dto.OAuth2AccessTokenRespDTO;
import cn.iocoder.mall.userservice.rpc.sms.dto.UserSendSmsCodeReqDTO;
import cn.iocoder.mall.userservice.rpc.sms.dto.UserVerifySmsCodeReqDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserCreateReqDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface PassportConvert {
PassportConvert INSTANCE = Mappers.getMapper(PassportConvert.class);
UserVerifySmsCodeReqDTO convert(PassportLoginBySmsReqVO bean);
UserCreateReqDTO convert02(PassportLoginBySmsReqVO bean);
UserSendSmsCodeReqDTO convert(PassportSendSmsRespVO bean);
PassportAccessTokenRespVO convert(OAuth2AccessTokenRespDTO bean);
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.mall.shopweb.convert.user;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressCreateReqVO;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressRespVO;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressUpdateReqVO;
import cn.iocoder.mall.userservice.rpc.address.dto.UserAddressCreateReqDTO;
import cn.iocoder.mall.userservice.rpc.address.dto.UserAddressRespDTO;
import cn.iocoder.mall.userservice.rpc.address.dto.UserAddressUpdateReqDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface UserAddressConvert {
UserAddressConvert INSTANCE = Mappers.getMapper(UserAddressConvert.class);
UserAddressUpdateReqDTO convert(UserAddressUpdateReqVO bean);
UserAddressRespVO convert(UserAddressRespDTO bean);
List<UserAddressRespVO> convertList(List<UserAddressRespDTO> list);
UserAddressCreateReqDTO convert(UserAddressCreateReqVO bean);
}

View File

@ -1,15 +0,0 @@
package cn.iocoder.mall.shopweb.convert.user;
import cn.iocoder.mall.shopweb.controller.user.vo.user.UserRespVO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface UserConvert {
UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
UserRespVO convert(UserRespDTO bean);
}

View File

@ -1,35 +0,0 @@
package cn.iocoder.mall.shopweb.service.promotion;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.promotion.api.rpc.banner.BannerFeign;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerListReqDTO;
import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerRespDTO;
import cn.iocoder.mall.shopweb.controller.promotion.vo.brand.BannerRespVO;
import cn.iocoder.mall.shopweb.convert.promotion.BannerConvert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Comparator;
import java.util.List;
/**
* Banner Manager
*/
@Service
@Validated
public class BannerManager {
@Autowired
private BannerFeign bannerFeign;
public List<BannerRespVO> listBanners() {
// 获取 Banner 列表
CommonResult<List<BannerRespDTO>> listBannersResult = bannerFeign.listBanners(
new BannerListReqDTO().setStatus(CommonStatusEnum.ENABLE.getValue()));
listBannersResult.checkError();
// 排序返回
listBannersResult.getData().sort(Comparator.comparing(BannerRespDTO::getSort));
return BannerConvert.INSTANCE.convertList(listBannersResult.getData());
}
}

View File

@ -28,68 +28,6 @@ import java.util.stream.Collectors;
@Service
public class CartManager {
@Autowired
private CartFeign cartFeign;
@Autowired
private PriceFeign priceFeign;
@Autowired
private PromotionActivityFeign promotionActivityFeign;
@Autowired
private ProductSkuFeign productSkuFeign;
/**
* 添加商品到购物车
*
* @param userId 用户编号
* @param skuId 商品 SKU 编号
* @param quantity 增加数量
*/
public void addCartItem(Integer userId, Integer skuId, Integer quantity) {
CommonResult<Boolean> addCartItemResult = cartFeign.addCartItem(new CartItemAddReqDTO().setUserId(userId)
.setSkuId(skuId).setQuantity(quantity));
addCartItemResult.checkError();
}
/**
* 查询用户在购物车中的商品数量
*
* @param userId 用户编号
* @return 商品数量
*/
public Integer sumCartItemQuantity(Integer userId) {
CommonResult<Integer> sumCartItemQuantityResult = cartFeign.sumCartItemQuantity(userId);
sumCartItemQuantityResult.checkError();
return sumCartItemQuantityResult.getData();
}
/**
* 更新购物车商品数量
*
* @param userId 用户编号
* @param skuId 商品 SKU 编号
* @param quantity 数量
*/
public void updateCartItemQuantity(Integer userId, Integer skuId, Integer quantity) {
CommonResult<Boolean> updateCartItemQuantityResult = cartFeign.updateCartItemQuantity(new CartItemUpdateQuantityReqDTO()
.setUserId(userId).setSkuId(skuId).setQuantity(quantity));
updateCartItemQuantityResult.checkError();
}
/**
* 更新购物车商品是否选中
*
* @param userId 用户编号
* @param skuIds 商品 SKU 编号数组
* @param selected 是否选中
*/
public void updateCartItemSelected(Integer userId, Set<Integer> skuIds, Boolean selected) {
CommonResult<Boolean> updateCartItemSelectedResult = cartFeign.updateCartItemSelected(new CartItemUpdateSelectedReqDTO()
.setUserId(userId).setSkuIds(skuIds).setSelected(selected));
updateCartItemSelectedResult.checkError();
}
/**
* 查询用户的购物车的商品列表
*

View File

@ -1,60 +0,0 @@
package cn.iocoder.mall.shopweb.service.user;
import cn.iocoder.common.framework.enums.UserTypeEnum;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportAccessTokenRespVO;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportLoginBySmsReqVO;
import cn.iocoder.mall.shopweb.controller.user.vo.passport.PassportSendSmsRespVO;
import cn.iocoder.mall.shopweb.convert.user.PassportConvert;
import cn.iocoder.mall.systemservice.rpc.oauth.OAuthFeign;
import cn.iocoder.mall.systemservice.rpc.oauth.dto.OAuth2AccessTokenRespDTO;
import cn.iocoder.mall.systemservice.rpc.oauth.dto.OAuth2CreateAccessTokenReqDTO;
import cn.iocoder.mall.systemservice.rpc.oauth.dto.OAuth2RefreshAccessTokenReqDTO;
import cn.iocoder.mall.userservice.enums.sms.UserSmsSceneEnum;
import cn.iocoder.mall.userservice.rpc.sms.UserSmsCodeFeign;
import cn.iocoder.mall.userservice.rpc.user.UserFeign;
import cn.iocoder.mall.userservice.rpc.user.dto.UserRespDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PassportManager {
private UserSmsCodeFeign userSmsCodeFeign;
private UserFeign userFeign;
@Autowired
private OAuthFeign oAuthFeign;
public PassportAccessTokenRespVO loginBySms(PassportLoginBySmsReqVO loginBySmsDTO, String ip) {
// 校验验证码
CommonResult<Boolean> verifySmsCodeResult = userSmsCodeFeign.verifySmsCode(
PassportConvert.INSTANCE.convert(loginBySmsDTO).setScene(UserSmsSceneEnum.LOGIN_BY_SMS.getValue()).setIp(ip));
verifySmsCodeResult.checkError();
// 获得用户
CommonResult<UserRespDTO> createUserResult = userFeign.createUserIfAbsent(
PassportConvert.INSTANCE.convert02(loginBySmsDTO).setIp(ip));
createUserResult.checkError();
// 创建访问令牌
CommonResult<OAuth2AccessTokenRespDTO> createAccessTokenResult = oAuthFeign.createAccessToken(
new OAuth2CreateAccessTokenReqDTO().setUserId(createUserResult.getData().getId())
.setUserType(UserTypeEnum.USER.getValue()).setCreateIp(ip));
createAccessTokenResult.checkError();
// 返回
return PassportConvert.INSTANCE.convert(createAccessTokenResult.getData());
}
public void sendSmsCode(PassportSendSmsRespVO sendSmsCodeDTO, String ip) {
CommonResult<Boolean> sendSmsCodeResult = userSmsCodeFeign.sendSmsCode(
PassportConvert.INSTANCE.convert(sendSmsCodeDTO).setIp(ip));
sendSmsCodeResult.checkError();
}
public PassportAccessTokenRespVO refreshToken(String refreshToken, String ip) {
CommonResult<OAuth2AccessTokenRespDTO> refreshAccessTokenResult = oAuthFeign.refreshAccessToken(
new OAuth2RefreshAccessTokenReqDTO().setRefreshToken(refreshToken).setCreateIp(ip));
refreshAccessTokenResult.checkError();
return PassportConvert.INSTANCE.convert(refreshAccessTokenResult.getData());
}
}

View File

@ -1,129 +0,0 @@
package cn.iocoder.mall.shopweb.service.user;
import cn.iocoder.common.framework.exception.GlobalException;
import cn.iocoder.common.framework.util.CollectionUtils;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressCreateReqVO;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressRespVO;
import cn.iocoder.mall.shopweb.controller.user.vo.address.UserAddressUpdateReqVO;
import cn.iocoder.mall.shopweb.convert.user.UserAddressConvert;
import cn.iocoder.mall.userservice.enums.address.UserAddressType;
import cn.iocoder.mall.userservice.rpc.address.UserAddressFeign;
import cn.iocoder.mall.userservice.rpc.address.dto.UserAddressRespDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import static cn.iocoder.common.framework.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
/**
* 用户收件地址 Manager
*/
@Service
public class UserAddressManager {
@Autowired
private UserAddressFeign userAddressFeign;
/**
* 创建用户收件地址
*
* @param userId 用户编号
* @param createVO 创建用户收件地址 VO
* @return 用户收件地址
*/
public Integer createUserAddress(Integer userId, UserAddressCreateReqVO createVO) {
CommonResult<Integer> createUserAddressResult = userAddressFeign.createUserAddress(
UserAddressConvert.INSTANCE.convert(createVO).setUserId(userId));
createUserAddressResult.checkError();
return createUserAddressResult.getData();
}
/**
* 更新用户收件地址
*
* @param userId 用户编号
* @param updateVO 更新用户收件地址 VO
*/
public void updateUserAddress(Integer userId, UserAddressUpdateReqVO updateVO) {
// 校验是否能够操作
check(userId, updateVO.getId());
// 执行更新
CommonResult<Boolean> updateUserAddressResult = userAddressFeign.updateUserAddress(UserAddressConvert.INSTANCE.convert(updateVO)
.setUserId(userId));
updateUserAddressResult.checkError();
}
/**
* 删除用户收件地址
*
* @param userId 用户编号
* @param userAddressId 用户收件地址编号
*/
public void deleteUserAddress(Integer userId, Integer userAddressId) {
// 校验是否能够操作
check(userId, userAddressId);
// 执行删除
CommonResult<Boolean> deleteUserAddressResult = userAddressFeign.deleteUserAddress(userAddressId);
deleteUserAddressResult.checkError();
}
/**
* 获得用户收件地址
*
* @param userId 用户编号
* @param userAddressId 用户收件地址编号
* @return 用户收件地址
*/
public UserAddressRespVO getUserAddress(Integer userId, Integer userAddressId) {
CommonResult<UserAddressRespDTO> getUserAddressResult = userAddressFeign.getUserAddress(userAddressId);
getUserAddressResult.checkError();
// 校验是否能够操作
this.check(userId, userAddressId);
return UserAddressConvert.INSTANCE.convert(getUserAddressResult.getData());
}
/**
* 获得用户收件地址列表
*
* @param userId 用户编号
* @return 用户收件地址列表
*/
public List<UserAddressRespVO> listUserAddresses(Integer userId) {
CommonResult<List<UserAddressRespDTO>> listUserAddressResult = userAddressFeign.listUserAddresses(userId, null);
listUserAddressResult.checkError();
return UserAddressConvert.INSTANCE.convertList(listUserAddressResult.getData());
}
/**
* 获得用户的默认收件地址
*
* @param userId 用户编号
* @return 用户收件地址
*/
public UserAddressRespVO getDefaultUserAddress(Integer userId) {
CommonResult<List<UserAddressRespDTO>> listUserAddressResult = userAddressFeign.listUserAddresses(userId, UserAddressType.DEFAULT.getType());
listUserAddressResult.checkError();
return !CollectionUtils.isEmpty(listUserAddressResult.getData()) ?
UserAddressConvert.INSTANCE.convert(listUserAddressResult.getData().get(0)) : null;
}
/**
* 校验用户收件地址是不是属于该用户
*
* @param userId 用户编号
* @param userAddressId 用户收件地址
*/
private void check(Integer userId, Integer userAddressId) {
CommonResult<UserAddressRespDTO> getUserAddressResult = userAddressFeign.getUserAddress(userAddressId);
getUserAddressResult.checkError();
this.check(userId, getUserAddressResult.getData());
}
private void check(Integer userId, UserAddressRespDTO userAddressRespDTO) {
if (!userAddressRespDTO.getUserId().equals(userId)) {
throw new GlobalException(FORBIDDEN);
}
}
}

View File

@ -1,33 +0,0 @@
package cn.iocoder.mall.shopweb.service.user;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.shopweb.controller.user.vo.user.UserRespVO;
import cn.iocoder.mall.shopweb.convert.user.UserConvert;
import cn.iocoder.mall.userservice.rpc.user.UserFeign;
import cn.iocoder.mall.userservice.rpc.user.dto.UserRespDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserUpdateReqDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserManager {
@Autowired
private UserFeign userFeign;
public UserRespVO getUser(Integer id) {
CommonResult<UserRespDTO> userResult = userFeign.getUser(id);
userResult.checkError();
return UserConvert.INSTANCE.convert(userResult.getData());
}
public void updateUserAvatar(Integer userId, String avatar) {
CommonResult<Boolean> updateUserResult = userFeign.updateUser(new UserUpdateReqDTO().setId(userId).setAvatar(avatar));
updateUserResult.checkError();
}
public void updateUserNickname(Integer userId, String nickname) {
CommonResult<Boolean> updateUserResult = userFeign.updateUser(new UserUpdateReqDTO().setId(userId).setNickname(nickname));
updateUserResult.checkError();
}
}

View File

@ -1,15 +0,0 @@
spring:
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: localhost:8848 # Nacos 服务器地址
namespace: dev # Nacos 命名空间
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
# address: spring-cloud://localhost:8848 # 指定 Dubbo 服务注册中心的地址
address: nacos://localhost:8848?namespace=dev # 指定 Dubbo 服务注册中心的地址

View File

@ -1,18 +0,0 @@
spring:
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: localhost:8848 # Nacos 服务器地址
namespace: dev # Nacos 命名空间
# Spring 主应用配置
main:
lazy-initialization: true # 开启延迟加载,保证本地开发的性能
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
# address: spring-cloud://localhost:8848 # 指定 Dubbo 服务注册中心的地址
address: nacos://localhost:8848?namespace=dev # 指定 Dubbo 服务注册中心的地址

View File

@ -1,75 +0,0 @@
# 服务器的配置项
server:
port: 18084
servlet:
context-path: /shop-api/
spring:
# Application 的配置项
application:
name: shop-web
# Profile 的配置项
profiles:
active: local
# SpringMVC 配置项
mvc:
throw-exception-if-no-handler-found: true # 匹配不到路径时,抛出 NoHandlerFoundException 异常
static-path-pattern: /doc.html # 静态资源的路径
# Dubbo 配置项
dubbo:
# Spring Cloud Alibaba Dubbo 专属配置
cloud:
subscribed-services: 'user-service,system-service' # 设置订阅的应用列表,默认为 * 订阅所有应用
# Dubbo 服务消费者的配置
consumer:
timeout: 10000
validation: true # 开启 Consumer 的参数校验
UserRpc:
version: 1.0.0
OAuth2Rpc:
version: 1.0.0
SystemAccessLogRpc:
version: 1.0.0
SystemExceptionLogRpc:
version: 1.0.0
ProductCategoryRpc:
version: 1.0.0
ProductSpuRpc:
version: 1.0.0
ProductSkuRpc:
version: 1.0.0
SearchProductRpc:
version: 1.0.0
PriceRpc:
version: 1.0.0
PromotionActivityRpc:
version: 1.0.0
CouponCardRpc:
version: 1.0.0
CouponTemplateRpc:
version: 1.0.0
BannerRpc:
version: 1.0.0
ProductRecommendRpc:
version: 1.0.0
TradeOrderRpc:
version: 1.0.0
PayTransactionRpc:
version: 1.0.0
UserSmsCodeRpc:
version: 1.0.0
UserAddressRpc:
version: 1.0.0
# Swagger 配置项
swagger:
title: 商城中心
description: 提供用户商城购物流程中的 API
version: 1.0.0
base-package: cn.iocoder.mall.shopweb.controller
# Actuator 监控配置项
management:
server.port: 38088 # 独立端口,避免被暴露出去
endpoints.web.exposure.include: '*' # 暴露所有监控端点

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>trade-service-project</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>trade-service-api</artifactId>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@ -39,11 +39,6 @@ public interface OrderErrorCodeConstants {
ErrorCode ORDER_RETURN_NOT_EXISTENT = new ErrorCode(1008000401, "退货订单不存在");
ErrorCode ORDER_RETURN_REFUND_FAILED = new ErrorCode(1008000402, "退款失败");
// ========== 购物车 ==========
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1008003000, "购物车项不存在");
ErrorCode CARD_ITEM_SKU_NOT_FOUND = new ErrorCode(1008003001, "商品不存在");
ErrorCode CARD_ITEM_SKU_QUANTITY_NOT_ENOUGH = new ErrorCode(1008003002, "商品库存不足");
// 工具类服务 1008004000
ErrorCode DICT_SERVER_INVOKING_FAIL = new ErrorCode(1008004000, "字典服务调用失败!");
ErrorCode ORDER_LOGISTICS_INVOKING_FAIL = new ErrorCode(1008004001, "订单物流调用失败!");

View File

@ -1,61 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.tradeservice.rpc.cart.dto.*;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* Title:
* Description:
*
* @author zhuyang
* @version 1.0 2021/10/9
*/
@FeignClient(value = "trade-service")
public interface CartFeign {
/**
* 添加商品到购物车
*
* @param addReqDTO 添加商品信息
* @return 成功
*/
@PostMapping("/trade/cart/addCartItem")
CommonResult<Boolean> addCartItem(@RequestBody CartItemAddReqDTO addReqDTO);
/**
* 更新购物车商品数量
*
* @param updateQuantityReqDTO 更新商品数量 DTO
* @return 成功
*/
@PostMapping("/trade/cart/updateCartItemQuantity")
CommonResult<Boolean> updateCartItemQuantity(@RequestBody CartItemUpdateQuantityReqDTO updateQuantityReqDTO);
/**
* 更新购物车商品是否选中
*
* @param updateSelectedReqDTO 更新商品是否选中 DTO
* @return 成功
*/
@PostMapping("/trade/cart/updateCartItemSelected")
CommonResult<Boolean> updateCartItemSelected(@RequestBody CartItemUpdateSelectedReqDTO updateSelectedReqDTO);
/**
* 删除购物车商品列表
*
* @param deleteListReqDTO 删除商品列表 DTO
* @return 成功
*/
@PostMapping("/trade/cart/deleteCartItems")
CommonResult<Boolean> deleteCartItems(@RequestBody CartItemDeleteListReqDTO deleteListReqDTO);
@GetMapping("/sumCartItemQuantity")
public CommonResult<Integer> sumCartItemQuantity(@RequestParam("userId") Integer userId) ;
@PostMapping("/trade/cart/listCartItems")
public CommonResult<List<CartItemRespDTO>> listCartItems(@RequestBody CartItemListReqDTO listReqDTO) ;
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 购物车添加购物项 Request DTO
*/
@Data
@Accessors(chain = true)
public class CartItemAddReqDTO implements Serializable {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 商品 SKU 编号
*/
@NotNull(message = "商品 SKU 编号不能为空")
private Integer skuId;
/**
* 数量
*/
@NotNull(message = "数量不能为空")
@Min(message = "数量必须大于 0", value = 1L)
private Integer quantity;
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.List;
/**
* 购物车删除商品列表 Request DTO
*/
@Data
@Accessors(chain = true)
public class CartItemDeleteListReqDTO implements Serializable {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 商品 SKU 编号列表
*/
@NotNull(message = "商品 SKU 编号列表不能为空")
private List<Integer> skuIds;
}

View File

@ -1,26 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 购物车的商品信息查询 BO
*/
@Data
@Accessors(chain = true)
public class CartItemListReqDTO implements Serializable {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 是否选中
*/
private Boolean selected;
}

View File

@ -1,67 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 购物车的商品信息 Response DTO
*/
@Data
@Accessors(chain = true)
public class CartItemRespDTO implements Serializable {
// ========= 基础字段 BEGIN =========
/**
* 编号唯一自增
*/
private Integer id;
/**
* 是否选中
*/
private Boolean selected;
// ========= 基础字段 END =========
// ========= 买家信息 BEGIN =========
/**
* 用户编号
*/
private Integer userId;
// ========= 买家信息 END =========
// ========= 商品信息 BEGIN =========
/**
* 商品 SPU 编号
*/
private Integer spuId;
/**
* 商品 SKU 编号
*/
private Integer skuId;
/**
* 商品购买数量
*/
private Integer quantity;
// ========= 商品信息 END =========
// ========= 优惠信息 BEGIN =========
// /**
// * 商品营销活动编号
// */
// private Integer activityId;
// /**
// * 商品营销活动类型
// */
// private Integer activityType;
// ========= 优惠信息 END =========
}

View File

@ -1,34 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 购物车更新数量 Request DTO
*/
@Data
@Accessors(chain = true)
public class CartItemUpdateQuantityReqDTO implements Serializable {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 商品 SKU 编号
*/
@NotNull(message = "商品 SKU 编号不能为空")
private Integer skuId;
/**
* 数量
*/
@NotNull(message = "数量不能为空")
@Min(message = "数量必须大于 0", value = 1L)
private Integer quantity;
}

View File

@ -1,33 +0,0 @@
package cn.iocoder.mall.tradeservice.rpc.cart.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Collection;
/**
* 购物车更新是否选中 Request DTO
*/
@Data
@Accessors(chain = true)
public class CartItemUpdateSelectedReqDTO implements Serializable {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 商品 SKU 编号列表
*/
@NotNull(message = "商品 SKU 编号列表不能为空")
private Collection<Integer> skuIds;
/**
* 是否选中
*/
@NotNull(message = "是否选中不能为空")
private Boolean selected;
}

View File

@ -1,147 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>trade-service-project</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>trade-service-app</artifactId>
<dependencies>
<!-- RPC 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-dubbo</artifactId>
</dependency>
<dependency>
<!-- 订单服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>trade-service-api</artifactId>
</dependency>
<dependency>
<!-- 系统服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 用户服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 商品服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>product-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 支付服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>pay-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<!-- 营销服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>promotion-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <!-- 需要开启 Web 容器,因为 Actuator 需要使用到 -->
</dependency>
<!-- MQ 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-rocketmq</artifactId>
</dependency>
<!-- Registry 和 Config 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<!-- Test 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<!-- 使用 spring-boot-maven-plugin 插件打包 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,17 +0,0 @@
package cn.iocoder.mall.tradeservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"cn.iocoder.mall.productservice.rpc","cn.iocoder.mall.promotion.api.rpc","cn.iocoder.mall.userservice.rpc"})
public class TradeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(TradeServiceApplication.class, args);
}
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.mall.tradeservice.client.user;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.userservice.rpc.address.UserAddressFeign;
import cn.iocoder.mall.userservice.rpc.address.dto.UserAddressRespDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class UserAddressClient {
@Autowired
private UserAddressFeign userAddressFeign;
public UserAddressRespDTO getUserAddress(Integer userAddressId, Integer userId) {
CommonResult<UserAddressRespDTO> getUserAddressResult = userAddressFeign.getUserAddress(userAddressId);
getUserAddressResult.checkError();
if (getUserAddressResult.getData() == null) {
return null;
}
// 如果用户编号不匹配则返回 null
return Objects.equals(getUserAddressResult.getData().getUserId(), userId) ?
getUserAddressResult.getData() : null;
}
}

View File

@ -1,12 +0,0 @@
package cn.iocoder.mall.tradeservice.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* Spring Aop 配置类
*/
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class AopConfiguration {
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.mall.tradeservice.config;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@MapperScan("cn.iocoder.mall.tradeservice.dal.mysql.mapper") // 扫描对应的 Mapper 接口
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理
public class DatabaseConfiguration {
// 数据库连接池 Druid
@Bean
public ISqlInjector sqlInjector() {
return new DefaultSqlInjector(); // MyBatis Plus 逻辑删除
}
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor(); // MyBatis Plus 分页插件
}
}

View File

@ -1,74 +0,0 @@
package cn.iocoder.mall.tradeservice.controller;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.tradeservice.rpc.cart.dto.*;
import cn.iocoder.mall.tradeservice.service.cart.CartManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController
@RequestMapping("/trade/cart")
public class CartController {
@Autowired
private CartManager cartManager;
/**
* 添加商品到购物车
*
* @param addReqDTO 添加商品信息
* @return 成功
*/
@PostMapping("addCartItem")
CommonResult<Boolean> addCartItem(@RequestBody CartItemAddReqDTO addReqDTO){
cartManager.addCartItem(addReqDTO);
return success(true);
}
/**
* 更新购物车商品数量
*
* @param updateQuantityReqDTO 更新商品数量 DTO
* @return 成功
*/
@PostMapping("updateCartItemQuantity")
CommonResult<Boolean> updateCartItemQuantity(@RequestBody CartItemUpdateQuantityReqDTO updateQuantityReqDTO){
cartManager.updateCartItemSelected(updateQuantityReqDTO);
return success(true);
}
/**
* 更新购物车商品是否选中
*
* @param updateSelectedReqDTO 更新商品是否选中 DTO
* @return 成功
*/
@PostMapping("updateCartItemSelected")
CommonResult<Boolean> updateCartItemSelected(@RequestBody CartItemUpdateSelectedReqDTO updateSelectedReqDTO){
cartManager.updateCartItemSelected(updateSelectedReqDTO);
return success(true);
}
/**
* 删除购物车商品列表
*
* @param deleteListReqDTO 删除商品列表 DTO
* @return 成功
*/
@PostMapping("deleteCartItems")
CommonResult<Boolean> deleteCartItems(@RequestBody CartItemDeleteListReqDTO deleteListReqDTO){
cartManager.deleteCartItems(deleteListReqDTO);
return success(true);
}
@GetMapping("/sumCartItemQuantity")
public CommonResult<Integer> sumCartItemQuantity(@RequestParam("userId") Integer userId) {
return success(cartManager.sumCartItemQuantity(userId));
}
@PostMapping("/listCartItems")
public CommonResult<List<CartItemRespDTO>> listCartItems(@RequestBody CartItemListReqDTO listReqDTO) {
return success(cartManager.listCartItems(listReqDTO));
}
}

View File

@ -1,30 +0,0 @@
package cn.iocoder.mall.tradeservice.convert.cart;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.cart.CartItemDO;
import cn.iocoder.mall.tradeservice.rpc.cart.dto.CartItemAddReqDTO;
import cn.iocoder.mall.tradeservice.rpc.cart.dto.CartItemListReqDTO;
import cn.iocoder.mall.tradeservice.rpc.cart.dto.CartItemRespDTO;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemAddBO;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemBO;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemListQueryBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface CartConvert {
CartConvert INSTANCE = Mappers.getMapper(CartConvert.class);
CartItemDO convert(CartItemAddBO bean);
CartItemAddBO convert(CartItemAddReqDTO bean);
List<CartItemBO> convertList(List<CartItemDO> list);
CartItemListQueryBO convert(CartItemListReqDTO bean);
List<CartItemRespDTO> convertList02(List<CartItemBO> list);
}

View File

@ -1,29 +0,0 @@
package cn.iocoder.mall.tradeservice.convert.order;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderDO;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderItemDO;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderItemRespDTO;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderRespDTO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface TradeOrderConvert {
TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class);
TradeOrderRespDTO convert(TradeOrderDO bean);
@Mapping(source = "records", target = "list")
PageResult<TradeOrderRespDTO> convertPage(IPage<TradeOrderDO> page);
List<TradeOrderItemRespDTO> convertList(List<TradeOrderItemDO> list);
TradeOrderItemRespDTO convert(TradeOrderItemDO bean);
}

View File

@ -1,73 +0,0 @@
package cn.iocoder.mall.tradeservice.dal.mysql.dataobject.cart;
import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 购物车的商品信息 DO
*/
@TableName("cart_item")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class CartItemDO extends DeletableDO {
// ========= 基础字段 BEGIN =========
/**
* 编号唯一自增
*/
private Integer id;
/**
* 是否选中
*/
private Boolean selected;
// ========= 基础字段 END =========
// ========= 买家信息 BEGIN =========
/**
* 用户编号
*/
private Integer userId;
// ========= 买家信息 END =========
// ========= 商品信息 BEGIN =========
/**
* 商品 SPU 编号
*/
private Integer spuId;
/**
* 商品 SKU 编号
*/
private Integer skuId;
/**
* 商品购买数量
*/
private Integer quantity;
// TODO 冗余字段
// ========= 商品信息 END =========
// ========= 优惠信息 BEGIN =========
// /**
// * 商品营销活动编号
// */
// private Integer activityId;
// /**
// * 商品营销活动类型
// */
// private Integer activityType;
// ========= 优惠信息 END =========
}

View File

@ -1,49 +0,0 @@
package cn.iocoder.mall.tradeservice.dal.mysql.mapper.cart;
import cn.iocoder.mall.mybatis.core.query.QueryWrapperX;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.cart.CartItemDO;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemListQueryBO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Repository
public interface CartItemMapper extends BaseMapper<CartItemDO> {
default CartItemDO selectByUserIdAndSkuId(Integer userId, Integer skuId) {
return selectOne(new QueryWrapper<CartItemDO>().eq("user_id", userId)
.eq("sku_id", skuId));
}
default List<CartItemDO> selectListByUserIdAndSkuIds(Integer userId, Collection<Integer> skuIds) {
return selectList(new QueryWrapperX<CartItemDO>().eq("user_id", userId)
.inIfPresent("sku_id", skuIds));
}
default void updateByIds(@Param("ids") Set<Integer> ids, @Param("updateObject") CartItemDO updateObject) {
// TODO 芋艿batch update mybatis plus 做拓展这里先临时处理
ids.forEach(id -> updateById(updateObject.setId(id)));
}
default Integer selectSumQuantityByUserId(Integer userId) {
// SQL sum 查询
List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartItemDO>()
.select("SUM(quantity) AS sumQuantity")
.eq("user_id", userId));
// 获得数量
return ((BigDecimal) result.get(0).get("sumQuantity")).intValue();
}
default List<CartItemDO> selectList(CartItemListQueryBO queryBO) {
return selectList(new QueryWrapperX<CartItemDO>().eq("user_id", queryBO.getUserId())
.eqIfPresent("selected", queryBO.getSelected()));
}
}

View File

@ -1,114 +0,0 @@
package cn.iocoder.mall.tradeservice.service.cart;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.productservice.rpc.sku.ProductSkuFeign;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.tradeservice.convert.cart.CartConvert;
import cn.iocoder.mall.tradeservice.rpc.cart.dto.*;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemBO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import static cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants.CARD_ITEM_SKU_NOT_FOUND;
/**
* 购物车 Manager
*/
@Service
public class CartManager {
@Autowired
private ProductSkuFeign productSkuFeign;
@Autowired
private CartService cartService;
/**
* 添加商品到购物车
*
* @param addReqDTO 添加商品信息
*/
public void addCartItem(CartItemAddReqDTO addReqDTO) {
// 校验商品 SKU 是否合法
ProductSkuRespDTO skuDTO = this.checkProductSku(addReqDTO.getSkuId());
// 添加购物车项
cartService.addCartItem(CartConvert.INSTANCE.convert(addReqDTO).setSpuId(skuDTO.getSpuId()), skuDTO.getQuantity());
}
/**
* 更新购物车商品数量
*
* @param updateQuantityReqDTO 更新商品数量
*/
public void updateCartItemSelected(CartItemUpdateQuantityReqDTO updateQuantityReqDTO) {
// 校验商品 SKU 是否合法
ProductSkuRespDTO skuDTO = this.checkProductSku(updateQuantityReqDTO.getSkuId());
// 更新购物车商品数量
cartService.updateCartItemQuantity(updateQuantityReqDTO.getUserId(), updateQuantityReqDTO.getSkuId(),
updateQuantityReqDTO.getQuantity(), skuDTO.getQuantity());
}
/**
* 更新购物车商品是否选中
*
* @param updateSelectedReqDTO 更新商品是否选中 DTO
*/
public void updateCartItemSelected(CartItemUpdateSelectedReqDTO updateSelectedReqDTO) {
cartService.updateCartItemSelected(updateSelectedReqDTO.getUserId(),
updateSelectedReqDTO.getSkuIds(), updateSelectedReqDTO.getSelected());
}
/**
* 删除购物车商品列表
*
* @param deleteListReqDTO 删除商品列表 DTO
*/
public void deleteCartItems(CartItemDeleteListReqDTO deleteListReqDTO) {
cartService.deleteCartItems(deleteListReqDTO.getUserId(),
deleteListReqDTO.getSkuIds());
}
/**
* 查询用户在购物车中的商品数量
*
* @param userId 用户编号
* @return 商品数量
*/
public Integer sumCartItemQuantity(Integer userId) {
return cartService.sumCartItemQuantity(userId);
}
/**
* 查询用户在购物车种的商品列表
*
* @param listReqDTO 查询条件 DTO
* @return 购物车中商品列表信息
*/
public List<CartItemRespDTO> listCartItems(CartItemListReqDTO listReqDTO) {
List<CartItemBO> cartItemBOs = cartService.listCartItems(CartConvert.INSTANCE.convert(listReqDTO));
return CartConvert.INSTANCE.convertList02(cartItemBOs);
}
/**
* 校验商品 SKU 是否合法
* 1. 是否存在
* 2. 是否下架
*
* @param skuId 商品 SKU 编号
* @return 商品 SKU 信息
*/
private ProductSkuRespDTO checkProductSku(Integer skuId) {
CommonResult<ProductSkuRespDTO> getProductSkuResult = productSkuFeign.getProductSku(skuId);
getProductSkuResult.checkError();
ProductSkuRespDTO skuDTO = getProductSkuResult.getData();
if (skuDTO == null || CommonStatusEnum.DISABLE.getValue().equals(skuDTO.getStatus())) {
throw ServiceExceptionUtil.exception(CARD_ITEM_SKU_NOT_FOUND);
}
return skuDTO;
}
}

View File

@ -1,136 +0,0 @@
package cn.iocoder.mall.tradeservice.service.cart;
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.util.CollectionUtils;
import cn.iocoder.mall.tradeservice.convert.cart.CartConvert;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.cart.CartItemDO;
import cn.iocoder.mall.tradeservice.dal.mysql.mapper.cart.CartItemMapper;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemAddBO;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemBO;
import cn.iocoder.mall.tradeservice.service.cart.bo.CartItemListQueryBO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants.CARD_ITEM_NOT_FOUND;
import static cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants.CARD_ITEM_SKU_QUANTITY_NOT_ENOUGH;
/**
* 购物车 Service
*/
@Service
@Validated
public class CartService {
@Autowired
private CartItemMapper cartItemMapper;
/**
* 添加商品到购物车
*
* @param addBO 添加商品信息
* @param skuQuantity 商品 SKU 的库存主要用于库存校验
*/
public void addCartItem(@Valid CartItemAddBO addBO, Integer skuQuantity) {
// 查询 CartItemDO
CartItemDO itemDO = cartItemMapper.selectByUserIdAndSkuId(addBO.getUserId(), addBO.getSkuId());
// 存在则进行数量更新
if (itemDO != null) {
if (addBO.getQuantity() + itemDO.getQuantity() > skuQuantity) {
// 校验库存
throw ServiceExceptionUtil.exception(CARD_ITEM_SKU_QUANTITY_NOT_ENOUGH);
}
cartItemMapper.updateById(new CartItemDO().setId(itemDO.getId()).setSelected(true)
.setQuantity(addBO.getQuantity() + itemDO.getQuantity()));
return;
}
// 不存在则进行插入
if (addBO.getQuantity() > skuQuantity) {
// 校验库存
throw ServiceExceptionUtil.exception(CARD_ITEM_SKU_QUANTITY_NOT_ENOUGH);
}
cartItemMapper.insert(CartConvert.INSTANCE.convert(addBO).setSelected(true));
}
/**
* 更新购物车商品数量
*
* @param userId 用户编号
* @param skuId 商品 SKU 编号
* @param quantity 数量
* @param skuQuantity 商品 SKU 的库存主要用于库存校验
*/
public void updateCartItemQuantity(Integer userId, Integer skuId, Integer quantity, Integer skuQuantity) {
if (quantity > skuQuantity) {
// 校验库存
throw ServiceExceptionUtil.exception(CARD_ITEM_SKU_QUANTITY_NOT_ENOUGH);
}
// 查询 CartItemDO
CartItemDO itemDO = cartItemMapper.selectByUserIdAndSkuId(userId, skuId);
if (itemDO == null) {
throw ServiceExceptionUtil.exception(CARD_ITEM_NOT_FOUND);
}
// 更新数量
cartItemMapper.updateById(new CartItemDO().setId(itemDO.getId()).setQuantity(quantity));
}
/**
* 更新购物车商品是否选中
*
* @param userId 用户编号
* @param skuIds 商品 SKU 编号数组
* @param selected 是否选中
*/
public void updateCartItemSelected(Integer userId, Collection<Integer> skuIds, Boolean selected) {
// 查询 CartItemDO 列表
List<CartItemDO> itemDOs = cartItemMapper.selectListByUserIdAndSkuIds(userId, skuIds);
if (skuIds.size() != itemDOs.size()) {
throw ServiceExceptionUtil.exception(CARD_ITEM_NOT_FOUND);
}
// 更新选中
cartItemMapper.updateByIds(CollectionUtils.convertSet(itemDOs, CartItemDO::getId),
new CartItemDO().setSelected(selected));
}
/**
* 购物车删除商品
*
* @param userId 用户编号
* @param skuIds 商品 SKU 编号的数组
*/
public void deleteCartItems(Integer userId, List<Integer> skuIds) {
// 查询 CartItemDO 列表
List<CartItemDO> itemDOs = cartItemMapper.selectListByUserIdAndSkuIds(userId, skuIds);
if (CollectionUtils.isEmpty(itemDOs)) {
return;
}
// 批量标记删除
cartItemMapper.deleteBatchIds(CollectionUtils.convertSet(itemDOs, CartItemDO::getId));
}
/**
* 查询用户在购物车中的商品数量
*
* @param userId 用户编号
* @return 商品数量
*/
public Integer sumCartItemQuantity(Integer userId) {
return cartItemMapper.selectSumQuantityByUserId(userId);
}
/**
* 查询用户在购物车种的商品列表
*
* @param queryBO 查询条件 BO
* @return 购物车中商品列表信息
*/
public List<CartItemBO> listCartItems(CartItemListQueryBO queryBO) {
List<CartItemDO> cartItemDOs = cartItemMapper.selectList(queryBO);
return CartConvert.INSTANCE.convertList(cartItemDOs);
}
}

View File

@ -1,38 +0,0 @@
package cn.iocoder.mall.tradeservice.service.cart.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/**
* 购物车添加购物项 Request DTO
*/
@Data
@Accessors(chain = true)
public class CartItemAddBO {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 商品 SPU 编号
*/
@NotNull(message = "商品 SPU 编号不能为空")
private Integer spuId;
/**
* 商品 SKU 编号
*/
@NotNull(message = "商品 SKU 编号不能为空")
private Integer skuId;
/**
* 数量
*/
@NotNull(message = "数量不能为空")
@Min(message = "数量必须大于 0", value = 1L)
private Integer quantity;
}

View File

@ -1,65 +0,0 @@
package cn.iocoder.mall.tradeservice.service.cart.bo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 购物车的商品信息 BO
*/
@Data
@Accessors(chain = true)
public class CartItemBO {
// ========= 基础字段 BEGIN =========
/**
* 编号唯一自增
*/
private Integer id;
/**
* 是否选中
*/
private Boolean selected;
// ========= 基础字段 END =========
// ========= 买家信息 BEGIN =========
/**
* 用户编号
*/
private Integer userId;
// ========= 买家信息 END =========
// ========= 商品信息 BEGIN =========
/**
* 商品 SPU 编号
*/
private Integer spuId;
/**
* 商品 SKU 编号
*/
private Integer skuId;
/**
* 商品购买数量
*/
private Integer quantity;
// ========= 商品信息 END =========
// ========= 优惠信息 BEGIN =========
// /**
// * 商品营销活动编号
// */
// private Integer activityId;
// /**
// * 商品营销活动类型
// */
// private Integer activityType;
// ========= 优惠信息 END =========
}

View File

@ -1,25 +0,0 @@
package cn.iocoder.mall.tradeservice.service.cart.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
* 购物车的商品信息查询 BO
*/
@Data
@Accessors(chain = true)
public class CartItemListQueryBO {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer userId;
/**
* 是否选中
*/
private Boolean selected;
}

View File

@ -1,48 +0,0 @@
package cn.iocoder.mall.tradeservice.service.order;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderCreateReqDTO;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderPageReqDTO;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderRespDTO;
import java.util.Collection;
/**
* 交易订单 Service 接口
*/
public interface TradeOrderService {
/**
* 创建交易订单
*
* @param createReqDTO 订单信息
* @return 订单编号
*/
Integer createTradeOrder(TradeOrderCreateReqDTO createReqDTO);
/**
* 获得订单交易
*
* @param tradeOrderId 订单交易编号
* @param fields 额外返回字段可见 {@link cn.iocoder.mall.tradeservice.enums.order.TradeOrderDetailFieldEnum}
* @return 订单交易
*/
TradeOrderRespDTO getTradeOrder(Integer tradeOrderId, Collection<String> fields);
/**
* 获得订单交易分页
*
* @param pageReqDTO 订单交易分页查询
* @return 订单交易分页结果
*/
PageResult<TradeOrderRespDTO> pageTradeOrder(TradeOrderPageReqDTO pageReqDTO);
/**
* 更新交易订单支付成功
*
* @param tradeOrderId 交易订单编号
* @param payAmount 支付金额
*/
void updateTradeOrderPaySuccess(Integer tradeOrderId, Integer payAmount);
}

View File

@ -1,279 +0,0 @@
package cn.iocoder.mall.tradeservice.service.order.impl;
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.util.CollectionUtils;
import cn.iocoder.common.framework.util.DateUtil;
import cn.iocoder.common.framework.util.MathUtil;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionCreateReqDTO;
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO;
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
import cn.iocoder.mall.tradeservice.client.pay.PayTransactionClient;
import cn.iocoder.mall.tradeservice.client.product.ProductSkuClient;
import cn.iocoder.mall.tradeservice.client.promotion.CouponCardClient;
import cn.iocoder.mall.tradeservice.client.promotion.PriceClient;
import cn.iocoder.mall.tradeservice.client.user.UserAddressClient;
import cn.iocoder.mall.tradeservice.config.TradeBizProperties;
import cn.iocoder.mall.tradeservice.convert.order.TradeOrderConvert;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderDO;
import cn.iocoder.mall.tradeservice.dal.mysql.dataobject.order.TradeOrderItemDO;
import cn.iocoder.mall.tradeservice.dal.mysql.mapper.order.TradeOrderItemMapper;
import cn.iocoder.mall.tradeservice.dal.mysql.mapper.order.TradeOrderMapper;
import cn.iocoder.mall.tradeservice.enums.logistics.LogisticsDeliveryTypeEnum;
import cn.iocoder.mall.tradeservice.enums.order.TradeOrderAfterSaleStatusEnum;
import cn.iocoder.mall.tradeservice.enums.order.TradeOrderDetailFieldEnum;
import cn.iocoder.mall.tradeservice.enums.order.TradeOrderStatusEnum;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderCreateReqDTO;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderPageReqDTO;
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderRespDTO;
import cn.iocoder.mall.tradeservice.service.order.TradeOrderService;
import cn.iocoder.mall.userservice.rpc.address.dto.UserAddressRespDTO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.common.framework.util.CollectionUtils.convertSet;
import static cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants.*;
import static cn.iocoder.mall.userservice.enums.UserErrorCodeConstants.USER_ADDRESS_NOT_FOUND;
/**
* 交易订单 Service 实现
*/
@Service
public class TradeOrderServiceImpl implements TradeOrderService {
@Autowired
private TradeOrderMapper tradeOrderMapper;
@Autowired
private TradeOrderItemMapper tradeOrderItemMapper;
@Autowired // 注入自己用于调用事务方法
private TradeOrderServiceImpl self;
@Autowired
private UserAddressClient userAddressClient;
@Autowired
private ProductSkuClient productSkuClient;
@Autowired
private PriceClient priceClient;
@Autowired
private CouponCardClient couponCardClient;
@Autowired
private PayTransactionClient payTransactionClient;
@Autowired
private TradeBizProperties tradeBizProperties;
@Override
// @GlobalTransactional TODO 芋艿使用 seata 实现分布式事务
public Integer createTradeOrder(TradeOrderCreateReqDTO createReqDTO) {
// 获得收件地址
UserAddressRespDTO userAddressRespDTO = userAddressClient.getUserAddress(createReqDTO.getUserAddressId(),
createReqDTO.getUserId());
if (userAddressRespDTO == null) {
throw ServiceExceptionUtil.exception(USER_ADDRESS_NOT_FOUND);
}
// 获得商品信息
List<ProductSkuRespDTO> listProductSkus = productSkuClient.listProductSkus(
convertSet(createReqDTO.getOrderItems(), TradeOrderCreateReqDTO.OrderItem::getSkuId),
ProductSkuDetailFieldEnum.SPU.getField());
if (listProductSkus.size() != createReqDTO.getOrderItems().size()) { // 校验获得的数量是否匹配
throw ServiceExceptionUtil.exception(ORDER_GET_GOODS_INFO_INCORRECT);
}
// 价格计算
PriceProductCalcRespDTO priceProductCalcRespDTO = priceClient.calcProductPrice(createReqDTO.getUserId(),
createReqDTO.getOrderItems().stream().map(orderItem -> new PriceProductCalcReqDTO.Item().setSkuId(orderItem.getSkuId())
.setQuantity(orderItem.getQuantity()).setSelected(true)).collect(Collectors.toList()),
createReqDTO.getCouponCardId());
// TODO 芋艿扣除库存
// 标记优惠劵已使用
if (createReqDTO.getCouponCardId() != null) {
couponCardClient.useCouponCard(createReqDTO.getUserId(), createReqDTO.getCouponCardId());
}
// 创建交易订单本地事务
TradeOrderDO tradeOrderDO = self.createTradeOrder0(createReqDTO, listProductSkus, priceProductCalcRespDTO, userAddressRespDTO);
// 创建支付订单对接支付服务
createPayTransaction(tradeOrderDO, createReqDTO, listProductSkus);
return tradeOrderDO.getId();
}
@Transactional
public TradeOrderDO createTradeOrder0(TradeOrderCreateReqDTO createReqDTO, List<ProductSkuRespDTO> listProductSkus,
PriceProductCalcRespDTO priceProductCalcRespDTO, UserAddressRespDTO userAddressRespDTO) {
// 构建 TradeOrderDO 对象并进行保存
TradeOrderDO tradeOrderDO = new TradeOrderDO();
// 1. 基本信息
tradeOrderDO.setUserId(createReqDTO.getUserId()).setOrderNo(generateTradeOrderNo())
.setOrderStatus(TradeOrderStatusEnum.WAITING_PAYMENT.getValue()).setRemark(createReqDTO.getRemark());
// 2. 价格 + 支付基本信息
tradeOrderDO.setBuyPrice(priceProductCalcRespDTO.getFee().getBuyTotal())
.setDiscountPrice(priceProductCalcRespDTO.getFee().getDiscountTotal())
.setLogisticsPrice(priceProductCalcRespDTO.getFee().getPostageTotal())
.setPresentPrice(priceProductCalcRespDTO.getFee().getPresentTotal())
.setPayPrice(0).setRefundPrice(0);
// 3. 收件 + 物流基本信息
tradeOrderDO.setDeliveryType(LogisticsDeliveryTypeEnum.EXPRESS.getDeliveryType())
.setReceiverName(userAddressRespDTO.getName()).setReceiverMobile(userAddressRespDTO.getMobile())
.setReceiverAreaCode(userAddressRespDTO.getAreaCode()).setReceiverDetailAddress(userAddressRespDTO.getDetailAddress());
// 4. 售后基本信息
tradeOrderDO.setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.NULL.getStatus());
// 5. 营销基本信息
tradeOrderDO.setCouponCardId(createReqDTO.getCouponCardId());
// 最终保存
tradeOrderMapper.insert(tradeOrderDO);
// 创建 TradeOrderItemDO 数组并进行保存
List<TradeOrderItemDO> tradeOrderItemDOs = new ArrayList<>(listProductSkus.size());
Map<Integer, ProductSkuRespDTO> listProductSkuMap = CollectionUtils.convertMap(listProductSkus, ProductSkuRespDTO::getId);
Map<Integer, PriceProductCalcRespDTO.Item> priceItemMap = new HashMap<>(); // 商品 SKU 价格的映射
priceProductCalcRespDTO.getItemGroups().forEach(itemGroup ->
itemGroup.getItems().forEach(item -> priceItemMap.put(item.getSkuId(), item)));
for (TradeOrderCreateReqDTO.OrderItem orderItem : createReqDTO.getOrderItems()) {
TradeOrderItemDO tradeOrderItemDO = new TradeOrderItemDO();
tradeOrderItemDOs.add(tradeOrderItemDO);
// 1. 基本信息
tradeOrderItemDO.setOrderId(tradeOrderDO.getId()).setStatus(tradeOrderDO.getOrderStatus());
// 2. 商品基本信息
ProductSkuRespDTO productSkuRespDTO = listProductSkuMap.get(orderItem.getSkuId());
tradeOrderItemDO.setSpuId(productSkuRespDTO.getSpuId()).setSkuId(productSkuRespDTO.getId())
.setSkuName(productSkuRespDTO.getSpu().getName())
.setSkuImage(CollectionUtils.getFirst(productSkuRespDTO.getSpu().getPicUrls()))
.setQuantity(orderItem.getQuantity());
// 3. 价格 + 支付基本信息
PriceProductCalcRespDTO.Item priceItem = priceItemMap.get(orderItem.getSkuId());
tradeOrderItemDO.setOriginPrice(priceItem.getOriginPrice()).setBuyPrice(priceItem.getBuyPrice())
.setPresentPrice(priceItem.getPresentPrice()).setBuyTotal(priceItem.getBuyTotal())
.setDiscountTotal(priceItem.getDiscountTotal()).setPresentTotal(priceItem.getPresentTotal())
.setRefundTotal(0);
// 4. 物流基本信息
// 5. 售后基本信息
tradeOrderItemDO.setAfterSaleStatus(TradeOrderAfterSaleStatusEnum.NULL.getStatus());
}
// 最终保存
tradeOrderItemMapper.insertList(tradeOrderItemDOs);
return tradeOrderDO;
}
private void createPayTransaction(TradeOrderDO tradeOrderDO, TradeOrderCreateReqDTO createReqDTO,
List<ProductSkuRespDTO> listProductSkus) {
// 创建支付单
String orderSubject = listProductSkus.get(0).getSpu().getName();
Date expireTime = DateUtil.addDate(Calendar.MINUTE, tradeBizProperties.getPayExpireTime());
Integer payTransactionId = payTransactionClient.createPayTransaction(
new PayTransactionCreateReqDTO().setUserId(createReqDTO.getUserId())
.setCreateIp(createReqDTO.getIp()).setAppId(tradeBizProperties.getPayAppId())
.setOrderId(tradeOrderDO.getId().toString()).setExpireTime(expireTime)
.setPrice(tradeOrderDO.getPresentPrice()).setOrderSubject(orderSubject)
.setOrderMemo("测试备注") // TODO 芋艿后面补充
.setOrderDescription("测试描述") // TODO 芋艿后面补充
);
// 更新
tradeOrderMapper.updateById(new TradeOrderDO().setId(tradeOrderDO.getId()).setPayTransactionId(payTransactionId));
}
private String generateTradeOrderNo() {
// wx
// 2014
// 10
// 27
// 20
// 09
// 39
// 5522657
// a690389285100
// 目前的算法
// 时间序列年月日时分秒 14
// 纯随机6 TODO 此处估计是会有问题的后续在调整
return DateUtil.format(new Date(), "yyyyMMddHHmmss") + // 时间序列
MathUtil.random(100000, 999999) // 随机为什么是这个范围因为偷懒
;
}
@Override
public TradeOrderRespDTO getTradeOrder(Integer tradeOrderId, Collection<String> fields) {
// 查询交易订单
TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(tradeOrderId);
if (tradeOrderDO == null) {
return null;
}
TradeOrderRespDTO tradeOrderRespDTO = TradeOrderConvert.INSTANCE.convert(tradeOrderDO);
// 查询交易订单项
if (fields.contains(TradeOrderDetailFieldEnum.ITEM.getField())) {
List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectListByOrderIds(
Collections.singleton(tradeOrderDO.getId()));
tradeOrderRespDTO.setOrderItems(TradeOrderConvert.INSTANCE.convertList(tradeOrderItemDOs));
}
// 返回
return tradeOrderRespDTO;
}
@Override
public PageResult<TradeOrderRespDTO> pageTradeOrder(TradeOrderPageReqDTO pageReqDTO) {
// 查询交易订单分页
IPage<TradeOrderDO> tradeOrderDOPage = tradeOrderMapper.selectPage(pageReqDTO);
PageResult<TradeOrderRespDTO> pageResult = TradeOrderConvert.INSTANCE.convertPage(tradeOrderDOPage);
if (CollectionUtils.isEmpty(pageResult.getList())) {
return pageResult;
}
// 查询交易订单项们
if (pageReqDTO.getFields().contains(TradeOrderDetailFieldEnum.ITEM.getField())) {
List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectListByOrderIds(
convertSet(tradeOrderDOPage.getRecords(), TradeOrderDO::getId));
Map<Integer, List<TradeOrderItemDO>> tradeOrderItemDOMultiMap = CollectionUtils.convertMultiMap(
tradeOrderItemDOs, TradeOrderItemDO::getOrderId);
pageResult.getList().forEach(tradeOrderRespDTO -> tradeOrderRespDTO.setOrderItems(
TradeOrderConvert.INSTANCE.convertList(tradeOrderItemDOMultiMap.get(tradeOrderRespDTO.getId()))));
}
// 返回
return pageResult;
}
@Override
@Transactional
public void updateTradeOrderPaySuccess(Integer tradeOrderId, Integer payAmount) {
// if (true) {
// throw new IllegalArgumentException("测试失败的情况");
// }
// 校验交易订单是否可以
TradeOrderDO tradeOrderDO = tradeOrderMapper.selectById(tradeOrderId);
if (tradeOrderDO == null) { // 订单不存在
throw ServiceExceptionUtil.exception(ORDER_NOT_EXISTENT);
}
if (!tradeOrderDO.getOrderStatus().equals(TradeOrderStatusEnum.WAITING_PAYMENT.getValue())) { // 状态不处于等待支付
throw ServiceExceptionUtil.exception(ORDER_STATUS_NOT_WAITING_PAYMENT);
}
if (!tradeOrderDO.getPresentPrice().equals(payAmount)) { // 支付金额不正确
throw ServiceExceptionUtil.exception(ORDER_PAY_AMOUNT_ERROR);
}
// 更新 TradeOrderDO 状态为已支付等待发货
TradeOrderDO updateOrderObj = new TradeOrderDO().setId(tradeOrderId)
.setOrderStatus(TradeOrderStatusEnum.WAIT_SHIPMENT.getValue())
.setPayPrice(payAmount)
.setPayTime(new Date());
int updateCount = tradeOrderMapper.update(updateOrderObj, TradeOrderStatusEnum.WAITING_PAYMENT.getValue());
if (updateCount <= 0) {
throw ServiceExceptionUtil.exception(ORDER_STATUS_NOT_WAITING_PAYMENT);
}
// 更新 TradeOrderItemDO 状态为已支付等待发货
TradeOrderItemDO updateOrderItemObj = new TradeOrderItemDO()
.setStatus(TradeOrderStatusEnum.WAIT_SHIPMENT.getValue());
tradeOrderItemMapper.updateListByOrderId(updateOrderItemObj, tradeOrderId,
TradeOrderStatusEnum.WAITING_PAYMENT.getValue());
}
}

View File

@ -1,21 +0,0 @@
spring:
# 数据源配置项
datasource:
url: jdbc:mysql://localhost:3306/mall_trade?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: zhuyang
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: localhost:8848 # Nacos 服务器地址
namespace: dev # Nacos 命名空间
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
# address: spring-cloud://localhost:8848 # 指定 Dubbo 服务注册中心的地址
address: nacos://localhost:8848?namespace=dev # 指定 Dubbo 服务注册中心的地址

View File

@ -1,32 +0,0 @@
spring:
# 数据源配置项
datasource:
url: jdbc:mysql://localhost:3306/mall_trade?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
driver-class-name: com.mysql.jdbc.Driver
username: root
password: zhuyang
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: localhost:8848 # Nacos 服务器地址
namespace: dev # Nacos 命名空间
# # Spring 主应用配置
# main:
# lazy-initialization: true # 开启延迟加载,保证本地开发的性能
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
# address: spring-cloud://localhost:8848 # 指定 Dubbo 服务注册中心的地址
address: nacos://localhost:8848?namespace=dev # 指定 Dubbo 服务注册中心的地址
# Dubbo 服务提供者的配置
provider:
tag: ${DUBBO_TAG} # Dubbo 路由分组
# MyBatis Plus 配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 本地开发环境下,多打印 SQL 到控制台

View File

@ -1,75 +0,0 @@
spring:
# Application 的配置项
application:
name: trade-service
# Profile 的配置项
profiles:
active: local
# MyBatis Plus 配置项
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
global-config:
db-config:
id-type: auto
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: cn.iocoder.mall.tradeservice.dal.mysql.dataobject
# Dubbo 配置项
dubbo:
# Spring Cloud Alibaba Dubbo 专属配置
cloud:
subscribed-services: '' # 设置订阅的应用列表,默认为 * 订阅所有应用
# Dubbo 提供者的协议
protocol:
name: dubbo
port: -1
# Dubbo 提供服务的扫描基础包
scan:
base-packages: cn.iocoder.mall.tradeservice.rpc
# Dubbo 服务提供者的配置
provider:
filter: -exception
validation: true # 开启 Provider 参数校验
version: 1.0.0 # 服务的版本号
# Dubbo 服务消费者的配置
consumer:
ErrorCodeRpc:
version: 1.0.0
ProductSkuRpc:
version: 1.0.0
UserAddressRpc:
version: 1.0.0
PriceRpc:
version: 1.0.0
CouponCardRpc:
version: 1.0.0
PayTransactionRpc:
version: 1.0.0
# RocketMQ 配置项
rocketmq:
name-server: localhost:9876
producer:
group: ${spring.application.name}-producer-group
# Actuator 监控配置项
management:
server.port: 38084 # 独立端口,避免被暴露出去
endpoints.web.exposure.include: '*' # 暴露所有监控端点
server.port: ${management.server.port} # 设置使用 Actuator 的服务器端口,因为 RPC 服务不需要 Web 端口
# Mall 配置项
mall:
# 错误码配置项对应 ErrorCodeProperties 配置类
error-code:
group: ${spring.application.name}
constants-class: cn.iocoder.mall.tradeservice.enums.OrderErrorCodeConstants
# 业务配置
biz:
pay-app-id: POd4RC6a
pay-expire-time: 120

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>onemall</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-service-project</artifactId>
<packaging>pom</packaging>
<description>用户服务</description>
<modules>
<module>user-service-api</module>
<module>user-service-app</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- onemall 基础 bom 文件 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-dependencies</artifactId>
<version>1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 自身项目 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>user-service-project</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-service-api</artifactId>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign-core</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
</project>

View File

@ -1,16 +0,0 @@
package cn.iocoder.mall.userservice.enums;
import cn.iocoder.common.framework.exception.ErrorCode;
/**
* 错误码枚举类
*
* user-service 服务使用 1-002-000-000
*/
public interface UserErrorCodeConstants {
// ========== 用户地址 ==========
ErrorCode USER_ADDRESS_NOT_FOUND = new ErrorCode(1001004000, "用户地址不存在!");
ErrorCode USER_GET_ADDRESS_NOT_EXISTS = new ErrorCode(1001004001, "获取的地址不存在!");
}

View File

@ -1,35 +0,0 @@
package cn.iocoder.mall.userservice.rpc.user;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.userservice.rpc.user.dto.UserCreateReqDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserPageReqDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserRespDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserUpdateReqDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* 用户短信验证码 Rpc 接口
*/
@FeignClient("user-service")
public interface UserFeign {
@GetMapping("/user/manage/getUser")
public CommonResult<UserRespDTO> getUser(@RequestParam("id") Integer id) ;
@GetMapping("/user/manage/listUsers")
public CommonResult<List<UserRespDTO>> listUsers(@RequestParam("userIds") List<Integer> userIds) ;
@PostMapping("/user/manage/createUserIfAbsent")
public CommonResult<UserRespDTO> createUserIfAbsent(@RequestBody UserCreateReqDTO createDTO);
@PostMapping("/user/manage/updateUser")
public CommonResult<Boolean> updateUser(@RequestBody UserUpdateReqDTO updateDTO);
@PostMapping("/user/manage/pageUser")
public CommonResult<PageResult<UserRespDTO>> pageUser(@RequestBody UserPageReqDTO pageDTO);
}

View File

@ -1,35 +0,0 @@
package cn.iocoder.mall.userservice.rpc.user.dto;
import cn.iocoder.common.framework.validator.Mobile;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 用户创建 Request DTO
*/
@Data
@Accessors(chain = true)
public class UserCreateReqDTO implements Serializable {
/**
* 手机号
*/
@NotNull(message = "手机号不能为空")
@Mobile(message = "手机格式不正确")
private String mobile;
/**
* 密码
*
* 允许为空自动生成
*/
private String password;
/**
* IP
*/
@NotNull(message = "IP 不能为空")
private String ip;
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.mall.userservice.rpc.user.dto;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.common.framework.vo.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 用户分页 Request DTO
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class UserPageReqDTO extends PageParam {
/**
* 昵称模糊匹配
*/
private String nickname;
/**
* 状态
*/
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
}

View File

@ -1,44 +0,0 @@
package cn.iocoder.mall.userservice.rpc.user.dto;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 用户信息 Response DTO
*/
@Data
@Accessors(chain = true)
public class UserRespDTO implements Serializable {
/**
* 用户编号
*/
private Integer id;
/**
* 手机号
*/
private String mobile;
/**
* 昵称
*/
private String nickname;
/**
* 头像
*/
private String avatar;
/**
* 用户状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 注册时间
*/
private Date createTime;
}

View File

@ -1,47 +0,0 @@
package cn.iocoder.mall.userservice.rpc.user.dto;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.common.framework.validator.InEnum;
import cn.iocoder.common.framework.validator.Mobile;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 用户更新 Request DTO
*/
@Data
@Accessors(chain = true)
public class UserUpdateReqDTO implements Serializable {
/**
* 用户编号
*/
@NotNull(message = "用户编号不能为空")
private Integer id;
/**
* 昵称
*/
private String nickname;
/**
* 头像
*/
private String avatar;
/**
* 状态
*/
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;
/**
* 手机号
*/
@Mobile
private String mobile;
/**
* 加密后的密码
*/
private String password;
}

View File

@ -1,108 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>user-service-project</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-service-app</artifactId>
<dependencies>
<!-- RPC 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-dubbo</artifactId>
</dependency>
<dependency>
<!-- 系统服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-service-api</artifactId>
</dependency>
<dependency>
<!-- 用户服务 -->
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-service-api</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <!-- 需要开启 Web 容器,因为 Actuator 需要使用到 -->
</dependency>
<!-- Registry 和 Config 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>mall-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<!-- 使用 spring-boot-maven-plugin 插件打包 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,17 +0,0 @@
package cn.iocoder.mall.userservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients(basePackages = {"cn.iocoder.mall.systemservice.rpc"})
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}

View File

@ -1,50 +0,0 @@
package cn.iocoder.mall.userservice.controller;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.common.framework.vo.PageResult;
import cn.iocoder.mall.userservice.manager.user.UserManager;
import cn.iocoder.mall.userservice.rpc.user.dto.UserCreateReqDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserPageReqDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserRespDTO;
import cn.iocoder.mall.userservice.rpc.user.dto.UserUpdateReqDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.common.framework.vo.CommonResult.success;
@RestController
@RequestMapping("/user/manage")
public class UserManageController {
@Autowired
private UserManager userManager;
@GetMapping("getUser")
public CommonResult<UserRespDTO> getUser(@RequestParam("id") Integer id) {
return success(userManager.getUser(id));
}
@GetMapping("listUsers")
public CommonResult<List<UserRespDTO>> listUsers(@RequestParam("userIds") List<Integer> userIds) {
return success(userManager.listUsers(userIds));
}
@PostMapping("createUserIfAbsent")
public CommonResult<UserRespDTO> createUserIfAbsent(@RequestBody UserCreateReqDTO createDTO) {
return success(userManager.createUserIfAbsent(createDTO));
}
@PostMapping("updateUser")
public CommonResult<Boolean> updateUser(@RequestBody UserUpdateReqDTO updateDTO) {
userManager.updateUser(updateDTO);
return success(true);
}
@PostMapping("pageUser")
public CommonResult<PageResult<UserRespDTO>> pageUser(@RequestBody UserPageReqDTO pageDTO) {
return success(userManager.pageUser(pageDTO));
}
}

View File

@ -1,62 +0,0 @@
package cn.iocoder.mall.userservice.dal.mysql.dataobject.sms;
import cn.iocoder.mall.mybatis.core.dataobject.BaseDO;
import cn.iocoder.mall.userservice.enums.sms.UserSmsSceneEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 手机验证码 DO
*
* idx_mobile 索引基于 {@link #mobile} 字段
*/
@TableName("user_sms_code")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class UserSmsCodeDO extends BaseDO {
/**
* 编号
*/
private Integer id;
/**
* 手机号
*/
private String mobile;
/**
* 验证码
*/
private String code;
/**
* 发送场景
*
* 外键 {@link UserSmsSceneEnum}
*/
private Integer scene;
/**
* 创建 IP
*/
private String createIp;
/**
* 今日发送的第几条
*/
private Integer todayIndex;
/**
* 是否使用
*/
private Boolean used;
/**
* 使用时间
*/
private Date usedTime;
/**
* 使用 IP
*/
private String usedIp;
}

View File

@ -1,57 +0,0 @@
package cn.iocoder.mall.userservice.dal.mysql.dataobject.user;
import cn.iocoder.common.framework.enums.CommonStatusEnum;
import cn.iocoder.mall.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 用户实体
*
* uk_mobile 索引基于 {@link #mobile} 字段
*/
@TableName(value = "users")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class UserDO extends BaseDO {
/**
* 用户编号
*/
private Integer id;
/**
* 昵称
*/
private String nickname;
/**
* 头像
*/
private String avatar;
/**
* 用户状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 手机
*/
private String mobile;
/**
* 经过加密的密码串
*/
private String password;
/**
* {@link #password} 的盐
*/
private String passwordSalt;
/**
* 注册 IP
*/
private String createIp;
}

View File

@ -1,73 +0,0 @@
package cn.iocoder.mall.userservice.dal.mysql.dataobject.user;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 用户三方开放平台授权例如QQ / 微博 / 微信等等
*
* TODO 优化点需要在改改
*/
@Data
@Accessors(chain = true)
public class UserThirdAuthDO {
/**
* 用户编号
*
* 外键 {@link UserDO#uid}
*/
private Long uid;
// ========== 授权相关字段
/**
* 用户的唯一标识
*/
private String openid;
/**
* 开放平台
*
* @see cn.iocoder.mall.user.api.constant.ThirdPlatformConstant
*/
private Integer platform;
/**
* 访问令牌
*/
private Date accessToken;
/**
* 过期时间
*/
private Date expireTime;
/**
* 刷新令牌
*/
private Date refreshToken;
/**
* 授权范围一般情况下使用逗号分隔
*/
private String scopes;
// ========== 基础信息
/**
* 用户昵称
*/
private String nickname;
/**
* 性别
*
* TODO 芋艿找地方统一枚举0-未知1-2-
*/
private Integer gender;
// TODO https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
// TODO 芋艿其他字段国家/省份/城市/地区等
// TODO 芋艿头像
// TODO 芋艿微信独有 unionid
/**
* 统一存储基础信息使用 JSON 格式化避免未有效解析的情况
*/
private String extras;
}

View File

@ -1,19 +0,0 @@
package cn.iocoder.mall.userservice.dal.mysql.mapper.address;
import cn.iocoder.mall.mybatis.core.query.QueryWrapperX;
import cn.iocoder.mall.userservice.dal.mysql.dataobject.address.UserAddressDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import javax.annotation.Nullable;
import java.util.List;
@Repository
public interface UserAddressMapper extends BaseMapper<UserAddressDO> {
default List<UserAddressDO> selectListByUserIdAndType(Integer userId, @Nullable Integer type) {
return selectList(new QueryWrapperX<UserAddressDO>().eq("user_id", userId)
.eqIfPresent("type", type));
}
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.mall.userservice.dal.mysql.mapper.sms;
import cn.iocoder.mall.mybatis.core.query.QueryWrapperX;
import cn.iocoder.mall.userservice.dal.mysql.dataobject.sms.UserSmsCodeDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface UserSmsCodeMapper extends BaseMapper<UserSmsCodeDO> {
/**
* 获得手机号的最后一个手机验证码
*
* @param mobile 手机号
* @param scene 发送场景选填
* @return 手机验证码
*/
default UserSmsCodeDO selectLastByMobile(String mobile, Integer scene) {
QueryWrapperX<UserSmsCodeDO> query = new QueryWrapperX<UserSmsCodeDO>()
.eq("mobile", mobile)
.eqIfPresent("scene", scene)
.orderByDesc("id")
.last("limit 1");
return selectOne(query);
}
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.mall.userservice.dal.mysql.mapper.user;
import cn.iocoder.mall.mybatis.core.query.QueryWrapperX;
import cn.iocoder.mall.userservice.dal.mysql.dataobject.user.UserDO;
import cn.iocoder.mall.userservice.service.user.bo.UserPageBO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<UserDO> {
default UserDO selectByMobile(String mobile) {
return selectOne(new QueryWrapper<UserDO>()
.eq("mobile", mobile)
);
}
default IPage<UserDO> selectPage(UserPageBO pageBO) {
return selectPage(new Page<>(pageBO.getPageNo(), pageBO.getPageSize()),
new QueryWrapperX<UserDO>().likeIfPresent("nickname", pageBO.getNickname())
.eqIfPresent("status", pageBO.getStatus()));
}
}

View File

@ -1,27 +0,0 @@
package cn.iocoder.mall.userservice.manager.sms;
import cn.iocoder.mall.userservice.rpc.sms.dto.UserSendSmsCodeReqDTO;
import cn.iocoder.mall.userservice.rpc.sms.dto.UserVerifySmsCodeReqDTO;
import cn.iocoder.mall.userservice.service.sms.UserSmsCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserSmsCodeManager {
@Autowired
private UserSmsCodeService userSmsCodeService;
public void sendSmsCode(UserSendSmsCodeReqDTO sendSmsCodeDTO) {
// 生成短信验证码
String smsCode = userSmsCodeService.createSmsCode(sendSmsCodeDTO.getMobile(),
sendSmsCodeDTO.getScene(), sendSmsCodeDTO.getIp());
// TODO 调用发送验证码
}
public void verifySmsCode(UserVerifySmsCodeReqDTO verifySmsCodeDTO) {
userSmsCodeService.verifySmsCode(verifySmsCodeDTO.getMobile(), verifySmsCodeDTO.getCode(),
verifySmsCodeDTO.getScene(), verifySmsCodeDTO.getIp());
}
}

Some files were not shown because too many files have changed in this diff Show More