将 onemall 老代码,统一到归档目录,后续不断迁移移除
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.iocoder.mall.shopweb.client.pay;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.PayTransactionFeign;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class PayTransactionClient {
|
||||
|
||||
|
||||
@Autowired
|
||||
private PayTransactionFeign payTransactionFeign;
|
||||
|
||||
public PayTransactionRespDTO getPayTransaction(Integer userId, String appId, String orderId) {
|
||||
CommonResult<PayTransactionRespDTO> getPayTransactionResult = payTransactionFeign.getPayTransaction(new PayTransactionGetReqDTO()
|
||||
.setAppId(appId).setOrderId(orderId));
|
||||
getPayTransactionResult.checkError();
|
||||
if (getPayTransactionResult.getData() == null) {
|
||||
return null;
|
||||
}
|
||||
// 如果用户编号不匹配,则返回 null
|
||||
return Objects.equals(getPayTransactionResult.getData().getUserId(), userId) ?
|
||||
getPayTransactionResult.getData() : null;
|
||||
}
|
||||
|
||||
public PayTransactionSubmitRespDTO submitPayTransaction(PayTransactionSubmitReqDTO submitReqDTO) {
|
||||
CommonResult<PayTransactionSubmitRespDTO> submitPayTransactionResult = payTransactionFeign.submitPayTransaction(submitReqDTO);
|
||||
submitPayTransactionResult.checkError();
|
||||
return submitPayTransactionResult.getData();
|
||||
}
|
||||
|
||||
public void updatePayTransactionSuccess(Integer payChannel, String params) {
|
||||
CommonResult<Boolean> updatePayTransactionSuccessResult = payTransactionFeign.updatePayTransactionSuccess(
|
||||
new PayTransactionSuccessReqDTO().setPayChannel(payChannel).setParams(params));
|
||||
updatePayTransactionSuccessResult.checkError();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package cn.iocoder.mall.shopweb.client.trade;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.tradeservice.rpc.order.TradeOrderFeign;
|
||||
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 org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Service
|
||||
public class TradeOrderClient {
|
||||
|
||||
|
||||
@Autowired
|
||||
private TradeOrderFeign tradeOrderFeign;
|
||||
public Integer createTradeOrder(TradeOrderCreateReqDTO createReqDTO) {
|
||||
CommonResult<Integer> createTradeOrderResult = tradeOrderFeign.createTradeOrder(createReqDTO);
|
||||
createTradeOrderResult.checkError();
|
||||
return createTradeOrderResult.getData();
|
||||
}
|
||||
|
||||
public PageResult<TradeOrderRespDTO> pageTradeOrder(TradeOrderPageReqDTO pageReqDTO) {
|
||||
CommonResult<PageResult<TradeOrderRespDTO>> pageTradeOrderResult = tradeOrderFeign.pageTradeOrder(pageReqDTO);
|
||||
pageTradeOrderResult.checkError();
|
||||
return pageTradeOrderResult.getData();
|
||||
}
|
||||
|
||||
public TradeOrderRespDTO getTradeOrder(Integer tradeOrderId, String... fields) {
|
||||
CommonResult<TradeOrderRespDTO> getTradeOrderResult = tradeOrderFeign.getTradeOrder(tradeOrderId, Arrays.asList(fields));
|
||||
getTradeOrderResult.checkError();
|
||||
return getTradeOrderResult.getData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
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;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package cn.iocoder.mall.shopweb.controller.pay;
|
||||
|
||||
import cn.iocoder.common.framework.util.HttpUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.payservice.enums.PayChannelEnum;
|
||||
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionSubmitReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionSubmitRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.pay.PayTransactionService;
|
||||
import cn.iocoder.security.annotations.RequiresAuthenticate;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@Api("支付交易 API")
|
||||
@RestController
|
||||
@RequestMapping("/pay/transaction")
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class PayTransactionController {
|
||||
|
||||
@Autowired
|
||||
private PayTransactionService payTransactionService;
|
||||
|
||||
// TODO 芋艿:这个 API 定义可能不太太合适,应该改成支付交易单号
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得支付交易")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "appId", required = true, value = "应用编号", example = "POd4RC6a"),
|
||||
@ApiImplicitParam(name = "orderId", required = true, value = "订单号", example = "1024"),
|
||||
})
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<PayTransactionRespVO> getPayTransaction(@RequestParam("appId") String appId,
|
||||
@RequestParam("orderId") String orderId) {
|
||||
return success(payTransactionService.getPayTransaction(UserSecurityContextHolder.getUserId(), appId, orderId));
|
||||
}
|
||||
|
||||
// TODO 芋艿:这个 API 定义可能不太太合适,应该改成支付交易单号
|
||||
@PostMapping("/submit")
|
||||
@ApiOperation("提交支付交易")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<PayTransactionSubmitRespVO> submitPayTransaction(HttpServletRequest request,
|
||||
PayTransactionSubmitReqVO submitReqVO) {
|
||||
return success(payTransactionService.submitPayTransaction(submitReqVO, HttpUtil.getIp(request)));
|
||||
}
|
||||
|
||||
@PostMapping(value = "pingxx_pay_success", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ApiOperation("Pingxx 支付成功回调")
|
||||
// @GetMapping(value = "pingxx_pay_success")
|
||||
public String updatePayTransactionSuccess(HttpServletRequest request) throws IOException {
|
||||
log.info("[pingxxPaySuccess][被回调]");
|
||||
// 读取 webhook
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try (BufferedReader reader = request.getReader()) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
}
|
||||
|
||||
// JSONObject bodyObj = JSON.parseObject(sb.toString());
|
||||
// bodyObj.put("webhookId", bodyObj.remove("id"));
|
||||
// String body = bodyObj.toString();
|
||||
payTransactionService.updatePayTransactionSuccess(PayChannelEnum.PINGXX.getId(), sb.toString());
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cn.iocoder.mall.shopweb.controller.pay.vo.transaction;
|
||||
|
||||
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 PayTransactionRespVO {
|
||||
|
||||
@ApiModelProperty(value = "交易编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "应用编号", required = true, example = "POd4RC6a")
|
||||
private String appId;
|
||||
|
||||
@ApiModelProperty(value = "订单号不能为空", required = true, example = "1024")
|
||||
private String orderId;
|
||||
|
||||
@ApiModelProperty(value = "商品名", required = true, example = "芋道源码")
|
||||
private String orderSubject;
|
||||
|
||||
@ApiModelProperty(value = "订单商品描述", required = true, example = "绵啾啾的")
|
||||
private String orderDescription;
|
||||
|
||||
@ApiModelProperty(value = "支付金额,单位:分。", required = true, example = "10")
|
||||
private Integer price;
|
||||
|
||||
@ApiModelProperty(value = "订单状态", required = true, example = "1", notes = "参见 PayTransactionStatusEnum 枚举")
|
||||
private Integer status;
|
||||
|
||||
@ApiModelProperty(value = "交易过期时间", required = true)
|
||||
private Date expireTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.mall.shopweb.controller.pay.vo.transaction;
|
||||
|
||||
import cn.iocoder.common.framework.validator.InEnum;
|
||||
import cn.iocoder.mall.payservice.enums.PayChannelEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("支付交易提交 Request VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionSubmitReqVO {
|
||||
|
||||
@ApiModelProperty(value = "应用编号", required = true, example = "POd4RC6a")
|
||||
@NotEmpty(message = "应用编号不能为空")
|
||||
private String appId;
|
||||
|
||||
@ApiModelProperty(value = "订单号", required = true, example = "1024")
|
||||
@NotEmpty(message = "订单号不能为空")
|
||||
private String orderId;
|
||||
|
||||
@ApiModelProperty(value = "支付渠道", required = true, example = "1", notes = "参见 PayChannelEnum 枚举")
|
||||
@InEnum(value = PayChannelEnum.class, message = "支付渠道必须是 {value}")
|
||||
@NotNull(message = "支付渠道")
|
||||
private Integer payChannel;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.iocoder.mall.shopweb.controller.pay.vo.transaction;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("支付交易提交 Response VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayTransactionSubmitRespVO {
|
||||
|
||||
@ApiModelProperty(value = "支付交易拓展单编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty(value = "调用三方平台的响应结果", required = true)
|
||||
private String invokeResponse;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
### /user-address/get-default 成功
|
||||
GET {{shop-api-base-url}}/product-category/list?pid=0
|
||||
|
||||
###
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.category.ProductCategoryRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.product.ProductCategoryManager;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@Api(tags = "商品分类 API")
|
||||
@RestController
|
||||
@RequestMapping("/product-category")
|
||||
@Validated
|
||||
public class ProductCategoryController {
|
||||
|
||||
@Autowired
|
||||
private ProductCategoryManager productCategoryManager;
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得商品分类的列表")
|
||||
@ApiImplicitParam(name = "pid", value = "父分类编号", required = true, example = "1024")
|
||||
public CommonResult<List<ProductCategoryRespVO>> listProductCategories(@RequestParam("pid") Integer pid) {
|
||||
return success(productCategoryManager.listProductCategories(pid));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
### /product-spu/page 计算商品 SKU 价格
|
||||
GET http://127.0.0.1:18084/shop-api/product-sku/cal-price?id=33
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
###
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.sku.ProductSkuCalcPriceRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.product.ProductSkuManager;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Api(tags = "商品 SKU API")
|
||||
@RestController
|
||||
@RequestMapping("/product-sku")
|
||||
@Validated
|
||||
public class ProductSkuController {
|
||||
|
||||
@Autowired
|
||||
private ProductSkuManager productSkuManager;
|
||||
|
||||
@GetMapping("/cal-price")
|
||||
@ApiOperation("计算商品 SKU 价格")
|
||||
@ApiImplicitParam(name = "id", required = true, value = "商品 SKU 编号", example = "1024")
|
||||
public CommonResult<ProductSkuCalcPriceRespVO> calcProductSkuPrice(@RequestParam("id") Integer id) {
|
||||
return CommonResult.success(productSkuManager.calcProductSkuPrice(UserSecurityContextHolder.getUserId(), id));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
### /product-spu/page 成功(全部)
|
||||
GET http://127.0.0.1:18084/shop-api/product-spu/page?pageNo=1&pageSize=10&keyword=骚气
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
### /product-spu/search-condition 成功
|
||||
GET http://127.0.0.1:18084/shop-api/product-spu/search-condition?keyword=骚气
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
### /product-spu/get-detail 成功
|
||||
GET http://127.0.0.1:18084/shop-api/product-spu/get-detail?id=63
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
###
|
||||
@@ -0,0 +1,52 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuDetailRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuSearchConditionRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.product.ProductSpuManager;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@Api(tags = "商品 SPU API")
|
||||
@RestController
|
||||
@RequestMapping("/product-spu")
|
||||
@Validated
|
||||
public class ProductSpuController {
|
||||
|
||||
@Autowired
|
||||
private ProductSpuManager productSpuManager;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得商品 SPU 的分页")
|
||||
public CommonResult<PageResult<ProductSpuRespVO>> pageProductSpu(ProductSpuPageReqVO pageReqVO) {
|
||||
return success(productSpuManager.pageProductSpu(pageReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/search-condition")
|
||||
@ApiOperation("获得商品的搜索条件")
|
||||
@ApiImplicitParam(name = "keyword", value = "关键字", example = "芋艿")
|
||||
public CommonResult<ProductSpuSearchConditionRespVO> getProductSpuSearchCondition(
|
||||
@RequestParam(value = "keyword", required = false) String keyword) {
|
||||
return success(productSpuManager.getProductSpuSearchCondition(keyword));
|
||||
}
|
||||
|
||||
@GetMapping("/get-detail")
|
||||
@ApiOperation("获得商品 SPU 的明细,包括 SKU 等等信息")
|
||||
@ApiImplicitParam(name = "id", required = true, value = "商品 SPU 编号", example = "1024")
|
||||
public CommonResult<ProductSpuDetailRespVO> getProductSpuDetail(@RequestParam("id") Integer id) {
|
||||
return success(productSpuManager.getProductSpuDetail(id));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product.vo.attr;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel(value = "商品规格 KEY + VALUE 对的 Response VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ProductAttrKeyValueRespVO {
|
||||
|
||||
@ApiModelProperty(value = "规格 KEY 编号", required = true, example = "1")
|
||||
private Integer attrKeyId;
|
||||
@ApiModelProperty(value = "规格 KEY 名字", required = true, example = "颜色")
|
||||
private String attrKeyName;
|
||||
@ApiModelProperty(value = "规格 VALUE 值", required = true, example = "10")
|
||||
private Integer attrValueId;
|
||||
@ApiModelProperty(value = "规格 VALUE 名字", required = true, example = "红色")
|
||||
private String attrValueName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product.vo.product;
|
||||
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.attr.ProductAttrKeyValueRespVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(value = "商品 SPU 详细 Response VO", description = "包括 SKU 信息 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ProductSpuDetailRespVO {
|
||||
|
||||
@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 = "http://www.iocoder.cn/xxx.jpg", notes = "多个之间,使用逗号分隔")
|
||||
private List<String> picUrls;
|
||||
|
||||
// ========== SKU =========
|
||||
|
||||
/**
|
||||
* SKU 数组
|
||||
*/
|
||||
private List<Sku> skus;
|
||||
|
||||
@ApiModel("商品 SKU 详细 Response VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Sku implements Serializable {
|
||||
|
||||
@ApiModelProperty(value = "sku 编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "SPU 编号", required = true, example = "1")
|
||||
private Integer spuId;
|
||||
@ApiModelProperty(value = "图片地址", required = true, example = "http://www.iocoder.cn")
|
||||
private String picURL;
|
||||
/**
|
||||
* 规格值数组
|
||||
*/
|
||||
private List<ProductAttrKeyValueRespVO> attrs;
|
||||
@ApiModelProperty(value = "价格,单位:分", required = true, example = "100")
|
||||
private Integer price;
|
||||
@ApiModelProperty(value = "库存数量", required = true, example = "100")
|
||||
private Integer quantity;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product.vo.product;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("商品 SPU 分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class ProductSpuPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "分类编号", example = "1")
|
||||
private Integer cid;
|
||||
@ApiModelProperty(value = "关键字", example = "芋艿")
|
||||
private String keyword;
|
||||
@ApiModelProperty(value = "排序字段", example = "buyPrice", notes = "参见 SearchProductPageQuerySortFieldEnum 枚举")
|
||||
private String sortField;
|
||||
@ApiModelProperty(value = "排序顺序", example = "1")
|
||||
private String sortOrder;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
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 ProductSpuSearchConditionRespVO {
|
||||
|
||||
@ApiModel("商品分类信息")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Category {
|
||||
|
||||
@ApiModelProperty(value = "分类编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "分类名称", required = true, example = "手机")
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 商品分类数组
|
||||
*/
|
||||
private List<Category> categories;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.iocoder.mall.shopweb.controller.product.vo.sku;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("计算商品 SKU 价格结果 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
// TODO 芋艿:swagger 注解
|
||||
public class ProductSkuCalcPriceRespVO {
|
||||
|
||||
/**
|
||||
* 原价格,单位:分。
|
||||
*/
|
||||
private Integer originalPrice;
|
||||
/**
|
||||
* 最终价格,单位:分。
|
||||
*/
|
||||
private Integer buyPrice;
|
||||
/**
|
||||
* 满减送促销活动
|
||||
*
|
||||
* TODO 芋艿,后续改成 VO
|
||||
*/
|
||||
private PromotionActivityRespDTO fullPrivilege;
|
||||
/**
|
||||
* 限时折扣促销活动
|
||||
*
|
||||
* TODO 芋艿,后续改成 VO
|
||||
*/
|
||||
private PromotionActivityRespDTO timeLimitedDiscount;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.brand.BannerRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.promotion.BannerManager;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/promotion/banner")
|
||||
@Api(tags = "Banner API")
|
||||
@Validated
|
||||
public class BannerController {
|
||||
|
||||
@Autowired
|
||||
private BannerManager bannerManager;
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得所有 Banner 列表")
|
||||
public CommonResult<List<BannerRespVO>> listBanners() {
|
||||
return success(bannerManager.listBanners());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
### /promotion/coupon-card/page 优惠劵分页(未使用)
|
||||
GET {{shop-api-base-url}}/promotion/coupon-card/page?pageNo=1&pageSize=10&status=1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
### /promotion/coupon-card/page 优惠劵分页(已使用)
|
||||
GET {{shop-api-base-url}}/promotion/coupon-card/page?pageNo=1&pageSize=10&status=2
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
### /promotion/coupon-card/page 优惠劵分页(已过期)
|
||||
GET {{shop-api-base-url}}/promotion/coupon-card/page?pageNo=1&pageSize=10&status=3
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
### /promotion/coupon-card/create 用户领取优惠劵(成功)
|
||||
POST {{shop-api-base-url}}/promotion/coupon-card/create
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
couponTemplateId=1
|
||||
|
||||
###
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card.CouponCardPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card.CouponCardRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.promotion.CouponCardManager;
|
||||
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.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/promotion/coupon-card")
|
||||
@Api(tags = "优惠劵 API")
|
||||
@Validated
|
||||
public class CouponCardController {
|
||||
|
||||
@Autowired
|
||||
private CouponCardManager couponCardManager;
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得优惠劵分页")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<PageResult<CouponCardRespVO>> pageCouponCard(CouponCardPageReqVO pageVO) {
|
||||
return success(couponCardManager.pageCouponCard(UserSecurityContextHolder.getUserId(),pageVO));
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
@ApiOperation("用户领取优惠劵")
|
||||
@ApiImplicitParam(name = "couponTemplateId", value = "优惠劵模板编号", required = true, example = "1024")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Integer> createCouponCard(@RequestParam("couponTemplateId") Integer couponTemplateId) {
|
||||
return success(couponCardManager.createCouponCard(UserSecurityContextHolder.getUserId(), couponTemplateId));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.template.CouponTemplateRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.promotion.CouponTemplateManager;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/promotion/coupon-template")
|
||||
@Api(tags = "优惠劵(码)模板 API")
|
||||
@Validated
|
||||
public class CouponTemplateController {
|
||||
|
||||
@Autowired
|
||||
private CouponTemplateManager couponTemplateManager;
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation(value = "优惠劵(码)模板信息")
|
||||
@ApiImplicitParam(name = "id", value = "优惠劵(码)模板编号", required = true, example = "10")
|
||||
public CommonResult<CouponTemplateRespVO> getCouponTemplate(@RequestParam("id") Integer id) {
|
||||
return success(couponTemplateManager.getCouponTemplate(id));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuRespVO;
|
||||
import cn.iocoder.mall.shopweb.service.promotion.ProductRecommendManager;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/promotion/product-recommend")
|
||||
@Api(tags = "商品推荐 API")
|
||||
@Validated
|
||||
public class ProductRecommendController {
|
||||
|
||||
@Autowired
|
||||
private ProductRecommendManager productRecommendManager;
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperation("获得所有商品推荐列表")
|
||||
public CommonResult<Map<Integer, Collection<ProductSpuRespVO>>> list() {
|
||||
return success(productRecommendManager.listProductRecommends());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion.vo.brand;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ApiModel("Banner Response VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class BannerRespVO {
|
||||
|
||||
@ApiModelProperty(value = "跳转链接", required = true, example = "http://www.baidu.com")
|
||||
private String url;
|
||||
@ApiModelProperty(value = "图片链接", required = true, example = "http://www.iocoder.cn/01.jpg")
|
||||
private String picUrl;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ApiModel("优惠劵分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class CouponCardPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "优惠码状态", required = true, example = "1", notes = "对应 CouponCardStatusEnum 枚举")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card;
|
||||
|
||||
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 CouponCardRespVO {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
@ApiModelProperty(value = "优惠劵编号", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "模板编号,自增唯一", required = true, example = "1")
|
||||
private Integer templateId;
|
||||
@ApiModelProperty(value = "优惠劵名", required = true, example = "大保剑")
|
||||
private String title;
|
||||
@ApiModelProperty(value = "优惠码状态", required = true, example = "参见 CouponCardStatusEnum 枚举")
|
||||
private Integer status;
|
||||
|
||||
// ========== 基本信息 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
@ApiModelProperty(value = "是否设置满多少金额可用,单位:分", required = true)
|
||||
private Integer priceAvailable;
|
||||
@ApiModelProperty(value = "固定日期-生效开始时间", required = true)
|
||||
private Date validStartTime;
|
||||
@ApiModelProperty(value = "固定日期-生效结束时间", required = true)
|
||||
private Date validEndTime;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
@ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
|
||||
private Integer preferentialType;
|
||||
@ApiModelProperty(value = "折扣百分比")
|
||||
private Integer percentOff;
|
||||
@ApiModelProperty(value = "优惠金额,单位:分")
|
||||
private Integer priceOff;
|
||||
@ApiModelProperty(value = "折扣上限")
|
||||
private Integer discountPriceLimit;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 使用情况 BEGIN ==========
|
||||
|
||||
// ========== 使用情况 END ==========
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.template;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel("优惠劵(码)模板 VO")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CouponTemplateRespVO {
|
||||
|
||||
// ========== 基本信息 BEGIN ==========
|
||||
@ApiModelProperty(value = "模板编号,自增唯一", required = true, example = "1")
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "标题", required = true, example = "优惠劵牛逼")
|
||||
private String title;
|
||||
@ApiModelProperty(value = "使用说明", required = true, example = "我只是描述")
|
||||
private String description;
|
||||
@ApiModelProperty(value = "优惠劵类型", required = true, example = "1", notes = "参见 CouponTemplateTypeEnum 枚举")
|
||||
private Integer type;
|
||||
/**
|
||||
* 码类型
|
||||
*
|
||||
* 1-一卡一码(UNIQUE)
|
||||
* 2-通用码(GENERAL)
|
||||
*
|
||||
* 【优惠码独有】 @see CouponCodeDO
|
||||
*/
|
||||
private Integer codeType;
|
||||
@ApiModelProperty(value = "优惠码状态", required = true, example = "1", notes = "参见 CouponTemplateStatusEnum 枚举")
|
||||
private Integer status;
|
||||
@ApiModelProperty(value = "每人限领个数", example = "1", notes = "null - 则表示不限制")
|
||||
private Integer quota;
|
||||
@ApiModelProperty(value = "发放总量", example = "100")
|
||||
private Integer total;
|
||||
// ========== 领取规则 END ==========
|
||||
|
||||
// ========== 使用规则 BEGIN ==========
|
||||
@ApiModelProperty(value = "是否设置满多少金额可用,单位:分", required = true, example = "0", notes = "0-不限制;大于0-多少金额可用")
|
||||
private Integer priceAvailable;
|
||||
@ApiModelProperty(value = "可用范围的类型", required = true, example = "10", notes = "参见 RangeTypeEnum 枚举")
|
||||
private Integer rangeType;
|
||||
@ApiModelProperty(value = "指定商品 / 分类列表,使用逗号分隔商品编号", example = "1,3,5")
|
||||
private List<Integer> rangeValues;
|
||||
@ApiModelProperty(value = "生效日期类型", example = "1", notes = "参见 CouponTemplateDateTypeEnum 枚举")
|
||||
private Integer dateType;
|
||||
@ApiModelProperty(value = "固定日期-生效开始时间", notes = "当 dateType 为固定日期时,非空")
|
||||
private Date validStartTime;
|
||||
@ApiModelProperty(value = "固定日期-生效结束时间", notes = "当 dateType 为固定日期时,非空")
|
||||
private Date validEndTime;
|
||||
@ApiModelProperty(value = "领取日期-开始天数", example = "0", notes = "例如,0-当天;1-次天")
|
||||
private Integer fixedStartTerm;
|
||||
@ApiModelProperty(value = "领取日期-结束天数", example = "1", notes = "当 dateType 为领取日期时,非空")
|
||||
private Integer fixedEndTerm;
|
||||
// ========== 使用规则 END ==========
|
||||
|
||||
// ========== 使用效果 BEGIN ==========
|
||||
@ApiModelProperty(value = "优惠类型", required = true, example = "1", notes = "参见 PreferentialTypeEnum 枚举")
|
||||
private Integer preferentialType;
|
||||
@ApiModelProperty(value = "折扣百分比", example = "80", notes = "当 preferentialType 为现金券时,非空")
|
||||
private Integer percentOff;
|
||||
@ApiModelProperty(value = "优惠金额,单位:分", example = "100", notes = "当 preferentialType 为折扣卷时,非空")
|
||||
private Integer priceOff;
|
||||
@ApiModelProperty(value = "折扣上限", example = "100", notes = "当 preferentialType 为折扣卷时,非空")
|
||||
private Integer discountPriceLimit;
|
||||
// ========== 使用效果 END ==========
|
||||
|
||||
// ========== 统计信息 BEGIN ==========
|
||||
@ApiModelProperty(value = "领取优惠券的次数", required = true)
|
||||
private Integer statFetchNum;
|
||||
// ========== 统计信息 END ==========
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.cart.CartDetailVO;
|
||||
import cn.iocoder.mall.shopweb.service.trade.CartManager;
|
||||
import cn.iocoder.security.annotations.RequiresAuthenticate;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
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 java.util.Set;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@Api(tags = "购物车 API")
|
||||
@RestController
|
||||
@RequestMapping("/cart")
|
||||
@Validated
|
||||
public class CartController {
|
||||
|
||||
@Autowired
|
||||
private CartManager cartManager;
|
||||
|
||||
@PostMapping("add")
|
||||
@ApiOperation("添加商品到购物车")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "skuId", value = "商品 SKU 编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "quantity", value = "增加数量", required = true, example = "1024")
|
||||
})
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Boolean> addCartItem(@RequestParam("skuId") Integer skuId,
|
||||
@RequestParam("quantity") Integer quantity) {
|
||||
cartManager.addCartItem(UserSecurityContextHolder.getUserId(), skuId, quantity);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("sum-quantity")
|
||||
@ApiOperation("查询用户在购物车中的商品数量")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Integer> sumCartItemQuantity() {
|
||||
return success(cartManager.sumCartItemQuantity(UserSecurityContextHolder.getUserId()));
|
||||
}
|
||||
|
||||
@GetMapping("/get-detail")
|
||||
@ApiOperation("查询用户的购物车的商品列表")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<CartDetailVO> getCartDetail() {
|
||||
return success(cartManager.getCartDetail(UserSecurityContextHolder.getUserId()));
|
||||
}
|
||||
|
||||
@PostMapping("update-quantity")
|
||||
@ApiOperation("更新购物车商品数量")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "skuId", value = "商品 SKU 编号", required = true, example = "1"),
|
||||
@ApiImplicitParam(name = "quantity", value = "增加数量", required = true, example = "1024")
|
||||
})
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Boolean> updateCartItemQuantity(@RequestParam("skuId") Integer skuId,
|
||||
@RequestParam("quantity") Integer quantity) {
|
||||
cartManager.updateCartItemQuantity(UserSecurityContextHolder.getUserId(), skuId, quantity);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("update-selected")
|
||||
@ApiOperation("更新购物车商品是否选中")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "skuIds", value = "商品 SKU 编号数组", required = true, example = "1,3"),
|
||||
@ApiImplicitParam(name = "selected", value = "是否选中", required = true, example = "true")
|
||||
})
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Boolean> updateCartItemSelected(@RequestParam("skuIds") Set<Integer> skuIds,
|
||||
@RequestParam("selected") Boolean selected) {
|
||||
cartManager.updateCartItemSelected(UserSecurityContextHolder.getUserId(), skuIds, selected);
|
||||
// 获得目前购物车明细
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
### /trade-order/confirm-create-order-info 基于商品,确认创建订单
|
||||
GET {{shop-api-base-url}}/trade-order/confirm-create-order-info?skuId=33&quantity=1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
### /trade-order/confirm-create-order-info-from-cart 基于购物车,确认创建订单
|
||||
GET {{shop-api-base-url}}/trade-order/confirm-create-order-info-from-cart
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
### /trade-order/confirm-create-order-info-from-cart 基于商品,创建订单
|
||||
POST {{shop-api-base-url}}/trade-order/create
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
|
||||
{
|
||||
"userAddressId": 19,
|
||||
"remark": "我是备注",
|
||||
"orderItems": [
|
||||
{
|
||||
"skuId": 3,
|
||||
"quantity": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
### /trade-order/page 获得订单交易分页
|
||||
GET {{shop-api-base-url}}/trade-order/page?status=1&pageNo=1&pageSize=10
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
###
|
||||
@@ -0,0 +1,84 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade;
|
||||
|
||||
import cn.iocoder.common.framework.util.HttpUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.security.user.core.context.UserSecurityContextHolder;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.*;
|
||||
import cn.iocoder.mall.shopweb.service.trade.TradeOrderService;
|
||||
import cn.iocoder.security.annotations.RequiresAuthenticate;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
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.servlet.http.HttpServletRequest;
|
||||
|
||||
import static cn.iocoder.common.framework.vo.CommonResult.success;
|
||||
|
||||
@Api(tags = "交易订单 API")
|
||||
@RestController
|
||||
@RequestMapping("/trade-order")
|
||||
@Validated
|
||||
public class TradeOrderController {
|
||||
|
||||
@Autowired
|
||||
private TradeOrderService tradeOrderService;
|
||||
|
||||
@GetMapping("confirm-create-order-info")
|
||||
@ApiOperation("基于商品,确认创建订单")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "skuId", required = true, value = "商品 SKU 编号", example = "1024"),
|
||||
@ApiImplicitParam(name = "quantity", required = true, value = "购买数量", example = "2"),
|
||||
@ApiImplicitParam(name = "couponCardId", value = "优惠劵编号", example = "1"),
|
||||
})
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<TradeOrderConfirmCreateInfoRespVO> getTradeOrderConfirmCreateInfo(
|
||||
@RequestParam("skuId") Integer skuId,
|
||||
@RequestParam("quantity") Integer quantity,
|
||||
@RequestParam(value = "couponCardId", required = false) Integer couponCardId) {
|
||||
return success(tradeOrderService.getOrderConfirmCreateInfo(UserSecurityContextHolder.getUserId(), skuId, quantity, couponCardId));
|
||||
}
|
||||
|
||||
@GetMapping("confirm-create-order-info-from-cart")
|
||||
@ApiOperation("基于购物车,确认创建订单")
|
||||
@ApiImplicitParam(name = "couponCardId", value = "优惠劵编号", example = "1")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<TradeOrderConfirmCreateInfoRespVO> getTradeOrderConfirmCreateInfoFromCart(
|
||||
@RequestParam(value = "couponCardId", required = false) Integer couponCardId) {
|
||||
return success(tradeOrderService.getOrderConfirmCreateInfoFromCart(UserSecurityContextHolder.getUserId(), couponCardId));
|
||||
}
|
||||
|
||||
@PostMapping("create")
|
||||
@ApiOperation("基于商品,创建订单")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Integer> createTradeOrder(@RequestBody TradeOrderCreateReqVO createReqVO,
|
||||
HttpServletRequest servletRequest) {
|
||||
return success(tradeOrderService.createTradeOrder(UserSecurityContextHolder.getUserId(),
|
||||
HttpUtil.getIp(servletRequest), createReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("create-from-cart")
|
||||
@ApiOperation("基于购物车,创建订单")
|
||||
@RequiresAuthenticate
|
||||
public CommonResult<Integer> createTradeOrder(TradeOrderCreateFromCartReqVO createReqVO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得交易订单")
|
||||
@ApiImplicitParam(name = "tradeOrderId", value = "交易订单编号", required = true)
|
||||
public CommonResult<TradeOrderRespVO> getTradeOrder(@RequestParam("tradeOrderId") Integer tradeOrderId) {
|
||||
return success(tradeOrderService.getTradeOrder(tradeOrderId));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("获得订单交易分页")
|
||||
public CommonResult<PageResult<TradeOrderRespVO>> pageTradeOrder(TradeOrderPageReqVO pageVO) {
|
||||
return success(tradeOrderService.pageTradeOrder(UserSecurityContextHolder.getUserId(), pageVO));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.cart;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.attr.ProductAttrKeyValueRespVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(value = "用户的购物车明细 Response VO") // TODO 芋艿:swagger 文档完善
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CartDetailVO {
|
||||
|
||||
/**
|
||||
* 商品分组数组
|
||||
*/
|
||||
private List<ItemGroup> itemGroups;
|
||||
/**
|
||||
* 费用
|
||||
*/
|
||||
private Fee fee;
|
||||
|
||||
/**
|
||||
* 商品分组
|
||||
*
|
||||
* 多个商品,参加同一个活动,从而形成分组。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class ItemGroup {
|
||||
|
||||
/**
|
||||
* 优惠活动
|
||||
*/
|
||||
private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒
|
||||
/**
|
||||
* 促销减少的金额
|
||||
*
|
||||
* 1. 若未参与促销活动,或不满足促销条件,返回 null
|
||||
* 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。
|
||||
*/
|
||||
private Integer activityDiscountTotal;
|
||||
/**
|
||||
* 商品数组
|
||||
*/
|
||||
private List<Sku> items;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Sku {
|
||||
|
||||
// SKU 自带信息
|
||||
/**
|
||||
* sku 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* SPU 信息
|
||||
*/
|
||||
private Spu spu;
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
private String picURL;
|
||||
/**
|
||||
* 规格值数组
|
||||
*/
|
||||
private List<ProductAttrKeyValueRespVO> attrs; // TODO 后面改下
|
||||
/**
|
||||
* 价格,单位:分
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 库存数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
// 非 SKU 自带信息
|
||||
|
||||
/**
|
||||
* 购买数量
|
||||
*/
|
||||
private Integer buyQuantity;
|
||||
/**
|
||||
* 是否选中
|
||||
*/
|
||||
private Boolean selected;
|
||||
/**
|
||||
* 优惠活动
|
||||
*/
|
||||
private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒
|
||||
/**
|
||||
* 原始单价,单位:分。
|
||||
*/
|
||||
private Integer originPrice;
|
||||
/**
|
||||
* 购买单价,单位:分
|
||||
*/
|
||||
private Integer buyPrice;
|
||||
/**
|
||||
* 最终价格,单位:分。
|
||||
*/
|
||||
private Integer presentPrice;
|
||||
/**
|
||||
* 购买总金额,单位:分
|
||||
*
|
||||
* 用途类似 {@link #presentTotal}
|
||||
*/
|
||||
private Integer buyTotal;
|
||||
/**
|
||||
* 优惠总金额,单位:分。
|
||||
*/
|
||||
private Integer discountTotal;
|
||||
/**
|
||||
* 最终总金额,单位:分。
|
||||
*
|
||||
* 注意,presentPrice * quantity 不一定等于 presentTotal 。
|
||||
* 因为,存在无法整除的情况。
|
||||
* 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。
|
||||
* 所以,需要存储一个该字段。
|
||||
*/
|
||||
private Integer presentTotal;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Spu {
|
||||
|
||||
/**
|
||||
* SPU 编号
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
// ========== 基本信息 =========
|
||||
/**
|
||||
* SPU 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer cid;
|
||||
/**
|
||||
* 商品主图地址
|
||||
*
|
||||
* 数组,以逗号分隔
|
||||
*
|
||||
* 建议尺寸:800*800像素,你可以拖拽图片调整顺序,最多上传15张
|
||||
*/
|
||||
private List<String> picUrls;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 费用(合计)
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Fee {
|
||||
|
||||
/**
|
||||
* 购买总价
|
||||
*/
|
||||
private Integer buyTotal;
|
||||
/**
|
||||
* 优惠总价
|
||||
*
|
||||
* 注意,满多少元包邮,不算在优惠中。
|
||||
*/
|
||||
private Integer discountTotal;
|
||||
/**
|
||||
* 邮费
|
||||
*/
|
||||
private Integer postageTotal;
|
||||
/**
|
||||
* 最终价格
|
||||
*
|
||||
* 计算公式 = 总价 - 优惠总价 + 邮费
|
||||
*/
|
||||
private Integer presentTotal;
|
||||
|
||||
public Fee() {
|
||||
}
|
||||
|
||||
public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
||||
this.buyTotal = buyTotal;
|
||||
this.discountTotal = discountTotal;
|
||||
this.postageTotal = postageTotal;
|
||||
this.presentTotal = presentTotal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮费信息 TODO 芋艿,未完成
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Postage {
|
||||
|
||||
/**
|
||||
* 需要满足多少钱,可以包邮。单位:分
|
||||
*/
|
||||
private Integer threshold;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.order;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.cart.CartDetailVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.attr.ProductAttrKeyValueRespVO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(value = "订单确认创建信息 Response VO") // TODO 芋艿:swagger 文档完善
|
||||
@Data
|
||||
@Accessors(chain = true) // TODO 芋艿:和 CartDetailVO、ProductSkuCalcPriceRespVO 有点重复,后续要优化下;
|
||||
public class TradeOrderConfirmCreateInfoRespVO {
|
||||
|
||||
/**
|
||||
* 商品分组数组
|
||||
*/
|
||||
private List<ItemGroup> itemGroups;
|
||||
/**
|
||||
* 费用
|
||||
*/
|
||||
private Fee fee;
|
||||
|
||||
/**
|
||||
* 优惠劵列表 TODO 芋艿,后续改改
|
||||
*/
|
||||
private List<CouponCardAvailableRespDTO> couponCards;
|
||||
|
||||
/**
|
||||
* 商品分组
|
||||
*
|
||||
* 多个商品,参加同一个活动,从而形成分组。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class ItemGroup {
|
||||
|
||||
/**
|
||||
* 优惠活动
|
||||
*/
|
||||
private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒
|
||||
/**
|
||||
* 促销减少的金额
|
||||
*
|
||||
* 1. 若未参与促销活动,或不满足促销条件,返回 null
|
||||
* 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。
|
||||
*/
|
||||
private Integer activityDiscountTotal;
|
||||
/**
|
||||
* 商品数组
|
||||
*/
|
||||
private List<CartDetailVO.Sku> items;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Sku {
|
||||
|
||||
// SKU 自带信息
|
||||
/**
|
||||
* sku 编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* SPU 信息
|
||||
*/
|
||||
private Spu spu;
|
||||
/**
|
||||
* 图片地址
|
||||
*/
|
||||
private String picURL;
|
||||
/**
|
||||
* 规格值数组
|
||||
*/
|
||||
private List<ProductAttrKeyValueRespVO> attrs; // TODO 后面改下
|
||||
/**
|
||||
* 价格,单位:分
|
||||
*/
|
||||
private Integer price;
|
||||
/**
|
||||
* 库存数量
|
||||
*/
|
||||
private Integer quantity;
|
||||
|
||||
// 非 SKU 自带信息
|
||||
|
||||
/**
|
||||
* 购买数量
|
||||
*/
|
||||
private Integer buyQuantity;
|
||||
/**
|
||||
* 优惠活动
|
||||
*/
|
||||
private PromotionActivityRespDTO activity; // TODO 芋艿,偷懒
|
||||
/**
|
||||
* 原始单价,单位:分。
|
||||
*/
|
||||
private Integer originPrice;
|
||||
/**
|
||||
* 购买单价,单位:分
|
||||
*/
|
||||
private Integer buyPrice;
|
||||
/**
|
||||
* 最终价格,单位:分。
|
||||
*/
|
||||
private Integer presentPrice;
|
||||
/**
|
||||
* 购买总金额,单位:分
|
||||
*
|
||||
* 用途类似 {@link #presentTotal}
|
||||
*/
|
||||
private Integer buyTotal;
|
||||
/**
|
||||
* 优惠总金额,单位:分。
|
||||
*/
|
||||
private Integer discountTotal;
|
||||
/**
|
||||
* 最终总金额,单位:分。
|
||||
*
|
||||
* 注意,presentPrice * quantity 不一定等于 presentTotal 。
|
||||
* 因为,存在无法整除的情况。
|
||||
* 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。
|
||||
* 所以,需要存储一个该字段。
|
||||
*/
|
||||
private Integer presentTotal;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Spu {
|
||||
|
||||
/**
|
||||
* SPU 编号
|
||||
*/
|
||||
private Integer id;
|
||||
|
||||
// ========== 基本信息 =========
|
||||
/**
|
||||
* SPU 名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer cid;
|
||||
/**
|
||||
* 商品主图地址
|
||||
*
|
||||
* 数组,以逗号分隔
|
||||
*
|
||||
* 建议尺寸:800*800像素,你可以拖拽图片调整顺序,最多上传15张
|
||||
*/
|
||||
private List<String> picUrls;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 费用(合计)
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Fee {
|
||||
|
||||
/**
|
||||
* 购买总价
|
||||
*/
|
||||
private Integer buyTotal;
|
||||
/**
|
||||
* 优惠总价
|
||||
*
|
||||
* 注意,满多少元包邮,不算在优惠中。
|
||||
*/
|
||||
private Integer discountTotal;
|
||||
/**
|
||||
* 邮费
|
||||
*/
|
||||
private Integer postageTotal;
|
||||
/**
|
||||
* 最终价格
|
||||
*
|
||||
* 计算公式 = 总价 - 优惠总价 + 邮费
|
||||
*/
|
||||
private Integer presentTotal;
|
||||
|
||||
public Fee() {
|
||||
}
|
||||
|
||||
public Fee(Integer buyTotal, Integer discountTotal, Integer postageTotal, Integer presentTotal) {
|
||||
this.buyTotal = buyTotal;
|
||||
this.discountTotal = discountTotal;
|
||||
this.postageTotal = postageTotal;
|
||||
this.presentTotal = presentTotal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 邮费信息 TODO 芋艿,未完成
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Postage {
|
||||
|
||||
/**
|
||||
* 需要满足多少钱,可以包邮。单位:分
|
||||
*/
|
||||
private Integer threshold;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.order;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel(value = "创建交易订单 VO,基于购物车")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TradeOrderCreateFromCartReqVO {
|
||||
|
||||
@ApiModelProperty(name = "收件地址编号", required = true, example = "1")
|
||||
@NotNull(message = "用户地址不能为空")
|
||||
private Integer userAddressId;
|
||||
@ApiModelProperty(name = "优惠劵编号", example = "1024")
|
||||
private Integer couponCardId;
|
||||
@ApiModelProperty(name = "备注", example = "1024")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.order;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
@ApiModel(value = "创建交易订单 VO,基于商品")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TradeOrderCreateReqVO {
|
||||
|
||||
@ApiModelProperty(name = "收件地址编号", required = true, example = "1")
|
||||
@NotNull(message = "收件地址不能为空")
|
||||
private Integer userAddressId;
|
||||
@ApiModelProperty(name = "优惠劵编号", example = "1024")
|
||||
private Integer couponCardId;
|
||||
@ApiModelProperty(name = "备注", example = "1024")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 订单商品项列表
|
||||
*/
|
||||
@NotNull(message = "必须选择购买的商品")
|
||||
private List<OrderItem> orderItems;
|
||||
|
||||
@ApiModel(value = "订单商品项")
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class OrderItem {
|
||||
|
||||
@ApiModelProperty(name = "商品 SKU 编号", required = true, example = "111")
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Integer skuId;
|
||||
@ApiModelProperty(name = "商品 SKU 购买数量", required = true, example = "1024")
|
||||
@NotNull(message = "商品 SKU 购买数量不能为空")
|
||||
@Min(value = 1, message = "商品 SKU 购买数量必须大于 0")
|
||||
private Integer quantity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.order;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@ApiModel("交易订单项 Response VO")
|
||||
@Data
|
||||
public class TradeOrderItemRespVO {
|
||||
|
||||
@ApiModelProperty(value = "id自增长", required = true)
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "订单编号", required = true)
|
||||
private Integer orderId;
|
||||
@ApiModelProperty(value = "订单项状态", required = true)
|
||||
private Integer status;
|
||||
@ApiModelProperty(value = "商品 SKU 编号", required = true)
|
||||
private Integer skuId;
|
||||
@ApiModelProperty(value = "商品 SPU 编号", required = true)
|
||||
private Integer spuId;
|
||||
@ApiModelProperty(value = "商品名字", required = true)
|
||||
private String skuName;
|
||||
@ApiModelProperty(value = "图片名字", required = true)
|
||||
private String skuImage;
|
||||
@ApiModelProperty(value = "商品数量", required = true)
|
||||
private Integer quantity;
|
||||
@ApiModelProperty(value = "原始单价,单位:分", required = true)
|
||||
private Integer originPrice;
|
||||
@ApiModelProperty(value = "购买单价,单位:分", required = true)
|
||||
private Integer buyPrice;
|
||||
@ApiModelProperty(value = "最终价格,单位:分", required = true)
|
||||
private Integer presentPrice;
|
||||
@ApiModelProperty(value = "购买总金额,单位:分", required = true)
|
||||
private Integer buyTotal;
|
||||
@ApiModelProperty(value = "优惠总金额,单位:分", required = true)
|
||||
private Integer discountTotal;
|
||||
@ApiModelProperty(value = "最终总金额,单位:分", required = true)
|
||||
private Integer presentTotal;
|
||||
@ApiModelProperty(value = "退款总金额,单位:分", required = true)
|
||||
private Integer refundTotal;
|
||||
@ApiModelProperty(value = "物流id")
|
||||
private Integer logisticsId;
|
||||
@ApiModelProperty(value = "售后状态", required = true)
|
||||
private Integer afterSaleStatus;
|
||||
@ApiModelProperty(value = "售后订单编号")
|
||||
private Integer afterSaleOrderId;
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.order;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageParam;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@ApiModel("交易订单分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TradeOrderPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "订单状态", example = "1", notes = "参见 TradeOrderStatusEnum 枚举")
|
||||
private Integer orderStatus;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package cn.iocoder.mall.shopweb.controller.trade.vo.order;
|
||||
|
||||
import lombok.*;
|
||||
import io.swagger.annotations.*;
|
||||
import java.util.*;
|
||||
|
||||
@ApiModel("订单交易 Response VO")
|
||||
@Data
|
||||
public class TradeOrderRespVO {
|
||||
|
||||
@ApiModelProperty(value = "订单编号", required = true)
|
||||
private Integer id;
|
||||
@ApiModelProperty(value = "用户编号", required = true)
|
||||
private Integer userId;
|
||||
@ApiModelProperty(value = "订单单号", required = true)
|
||||
private String orderNo;
|
||||
@ApiModelProperty(value = "订单状态", required = true)
|
||||
private Integer orderStatus;
|
||||
@ApiModelProperty(value = "备注")
|
||||
private String remark;
|
||||
@ApiModelProperty(value = "订单结束时间")
|
||||
private Date endTime;
|
||||
@ApiModelProperty(value = "订单金额(总金额),单位:分", required = true)
|
||||
private Integer buyPrice;
|
||||
@ApiModelProperty(value = "优惠总金额,单位:分", required = true)
|
||||
private Integer discountPrice;
|
||||
@ApiModelProperty(value = "物流金额,单位:分", required = true)
|
||||
private Integer logisticsPrice;
|
||||
@ApiModelProperty(value = "最终金额,单位:分", required = true)
|
||||
private Integer presentPrice;
|
||||
@ApiModelProperty(value = "支付金额,单位:分", required = true)
|
||||
private Integer payPrice;
|
||||
@ApiModelProperty(value = "退款金额,单位:分", required = true)
|
||||
private Integer refundPrice;
|
||||
@ApiModelProperty(value = "付款时间")
|
||||
private Date payTime;
|
||||
@ApiModelProperty(value = "支付订单编号")
|
||||
private Integer payTransactionId;
|
||||
@ApiModelProperty(value = "支付渠道")
|
||||
private Integer payChannel;
|
||||
@ApiModelProperty(value = "配送类型", required = true)
|
||||
private Integer deliveryType;
|
||||
@ApiModelProperty(value = "发货时间")
|
||||
private Date deliveryTime;
|
||||
@ApiModelProperty(value = "收货时间")
|
||||
private Date receiveTime;
|
||||
@ApiModelProperty(value = "收件人名称", required = true)
|
||||
private String receiverName;
|
||||
@ApiModelProperty(value = "手机号", required = true)
|
||||
private String receiverMobile;
|
||||
@ApiModelProperty(value = "地区编码", required = true)
|
||||
private Integer receiverAreaCode;
|
||||
@ApiModelProperty(value = "收件详细地址", required = true)
|
||||
private String receiverDetailAddress;
|
||||
@ApiModelProperty(value = "售后状态", required = true)
|
||||
private Integer afterSaleStatus;
|
||||
@ApiModelProperty(value = "优惠劵编号")
|
||||
private Integer couponCardId;
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 订单项数组
|
||||
*
|
||||
* // TODO 芋艿,后续考虑怎么优化下,目前是内嵌了别的 dto
|
||||
*/
|
||||
private List<TradeOrderItemRespVO> orderItems;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
### /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
|
||||
|
||||
###
|
||||
@@ -0,0 +1,56 @@
|
||||
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)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
### /user-address/get-default 成功
|
||||
GET {{shop-api-base-url}}/user-address/get-default
|
||||
Authorization: Bearer {{user-access-token}}
|
||||
dubbo-tag: {{dubboTag}}
|
||||
|
||||
###
|
||||
@@ -0,0 +1,80 @@
|
||||
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()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.shopweb.convert.pay;
|
||||
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionRespDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionSubmitReqDTO;
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionSubmitRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionSubmitReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionSubmitRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface PayTransactionConvert {
|
||||
|
||||
PayTransactionConvert INSTANCE = Mappers.getMapper(PayTransactionConvert.class);
|
||||
|
||||
PayTransactionSubmitReqDTO convert(PayTransactionSubmitReqVO bean);
|
||||
|
||||
PayTransactionSubmitRespVO convert(PayTransactionSubmitRespDTO bean);
|
||||
|
||||
PayTransactionRespVO convert(PayTransactionRespDTO bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.mall.shopweb.convert.product;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.sku.ProductSkuCalcPriceRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface ProductSkuConvert {
|
||||
|
||||
ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class);
|
||||
|
||||
default ProductSkuCalcPriceRespVO convert(PriceProductCalcRespDTO.Item item,
|
||||
PromotionActivityRespDTO fullPrivilege, PromotionActivityRespDTO timeLimitedDiscount) {
|
||||
return new ProductSkuCalcPriceRespVO().setOriginalPrice(item.getOriginPrice()).setBuyPrice(item.getBuyPrice())
|
||||
.setFullPrivilege(fullPrivilege).setTimeLimitedDiscount(timeLimitedDiscount);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.iocoder.mall.shopweb.convert.product;
|
||||
|
||||
import cn.iocoder.common.framework.util.StringUtils;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.common.framework.vo.SortingField;
|
||||
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuDetailRespDTO;
|
||||
import cn.iocoder.mall.searchservice.rpc.product.dto.SearchProductPageReqDTO;
|
||||
import cn.iocoder.mall.searchservice.rpc.product.dto.SearchProductRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuDetailRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuSearchConditionRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ProductSpuConvert {
|
||||
|
||||
ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class);
|
||||
|
||||
default SearchProductPageReqDTO convert(ProductSpuPageReqVO bean) {
|
||||
SearchProductPageReqDTO reqDTO = new SearchProductPageReqDTO()
|
||||
.setCid(bean.getCid()).setKeyword(bean.getKeyword());
|
||||
reqDTO.setPageNo(bean.getPageNo()).setPageSize(bean.getPageSize());
|
||||
if (StringUtils.hasText(bean.getSortField()) && StringUtils.hasText(bean.getSortOrder())) {
|
||||
reqDTO.setSorts(Collections.singletonList(new SortingField(bean.getSortField(), bean.getSortOrder())));
|
||||
}
|
||||
return reqDTO;
|
||||
}
|
||||
|
||||
PageResult<ProductSpuRespVO> convertPage(PageResult<SearchProductRespDTO> page);
|
||||
|
||||
List<ProductSpuSearchConditionRespVO.Category> convertList(List<ProductCategoryRespDTO> list);
|
||||
|
||||
ProductSpuDetailRespVO convert(ProductSpuDetailRespDTO bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.shopweb.convert.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardPageReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card.CouponCardPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card.CouponCardRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* 优惠劵 Convert
|
||||
*/
|
||||
@Mapper
|
||||
public interface CouponCardConvert {
|
||||
|
||||
CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class);
|
||||
|
||||
PageResult<CouponCardRespVO> convertPage(PageResult<CouponCardRespDTO> page);
|
||||
|
||||
CouponCardPageReqDTO convert(CouponCardPageReqVO bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.iocoder.mall.shopweb.convert.promotion;
|
||||
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.template.CouponTemplateRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.template.CouponTemplateRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface CouponTemplateConvert {
|
||||
|
||||
CouponTemplateConvert INSTANCE = Mappers.getMapper(CouponTemplateConvert.class);
|
||||
|
||||
CouponTemplateRespVO convert(CouponTemplateRespDTO bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.iocoder.mall.shopweb.convert.promotion;
|
||||
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuRespVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface ProductRecommendConvert {
|
||||
|
||||
ProductRecommendConvert INSTANCE = Mappers.getMapper(ProductRecommendConvert.class);
|
||||
|
||||
ProductSpuRespVO convert(ProductSpuRespDTO bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.mall.shopweb.convert.trade;
|
||||
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.cart.CartDetailVO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface CartConvert {
|
||||
|
||||
CartConvert INSTANCE = Mappers.getMapper(CartConvert.class);
|
||||
|
||||
CartDetailVO.Fee convert(PriceProductCalcRespDTO.Fee bean);
|
||||
|
||||
@Mapping(source = "sku.id", target = "id")
|
||||
CartDetailVO.Sku convert(PriceProductCalcRespDTO.Item item, ProductSkuRespDTO sku, PromotionActivityRespDTO activity);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package cn.iocoder.mall.shopweb.convert.trade;
|
||||
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderConfirmCreateInfoRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderCreateReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderRespVO;
|
||||
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 org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mapper
|
||||
public interface TradeOrderConvert {
|
||||
|
||||
TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class);
|
||||
|
||||
TradeOrderConfirmCreateInfoRespVO.Fee convert(PriceProductCalcRespDTO.Fee bean);
|
||||
|
||||
default List<CouponCardAvailableListReqDTO.Item> convertList(List<PriceProductCalcRespDTO.ItemGroup> itemGroups) {
|
||||
List<CouponCardAvailableListReqDTO.Item> items = new ArrayList<>();
|
||||
itemGroups.forEach(itemGroup -> items.addAll(itemGroup.getItems().stream().map(
|
||||
item -> new CouponCardAvailableListReqDTO.Item()
|
||||
.setSpuId(item.getSpuId())
|
||||
.setSkuId(item.getSkuId())
|
||||
.setCid(item.getCid())
|
||||
.setPrice(item.getBuyPrice())
|
||||
.setQuantity(item.getBuyQuantity()))
|
||||
.collect(Collectors.toList())));
|
||||
return items;
|
||||
}
|
||||
|
||||
TradeOrderCreateReqDTO convert(TradeOrderCreateReqVO bean);
|
||||
|
||||
TradeOrderPageReqDTO convert(TradeOrderPageReqVO bean);
|
||||
|
||||
PageResult<TradeOrderRespVO> convertPage(PageResult<TradeOrderRespDTO> page);
|
||||
|
||||
TradeOrderRespVO convert(TradeOrderRespDTO bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.iocoder.mall.shopweb.service.pay;
|
||||
|
||||
import cn.iocoder.mall.payservice.rpc.transaction.dto.PayTransactionSubmitRespDTO;
|
||||
import cn.iocoder.mall.shopweb.client.pay.PayTransactionClient;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionSubmitReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.pay.vo.transaction.PayTransactionSubmitRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.pay.PayTransactionConvert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PayTransactionService {
|
||||
|
||||
@Autowired
|
||||
private PayTransactionClient payTransactionClient;
|
||||
|
||||
public PayTransactionSubmitRespVO submitPayTransaction(PayTransactionSubmitReqVO submitReqVO, String ip) {
|
||||
PayTransactionSubmitRespDTO submitPayTransaction = payTransactionClient.submitPayTransaction(
|
||||
PayTransactionConvert.INSTANCE.convert(submitReqVO).setCreateIp(ip));
|
||||
return PayTransactionConvert.INSTANCE.convert(submitPayTransaction);
|
||||
}
|
||||
|
||||
public PayTransactionRespVO getPayTransaction(Integer userId, String appId, String orderId) {
|
||||
return PayTransactionConvert.INSTANCE.convert(payTransactionClient.getPayTransaction(userId, appId, orderId));
|
||||
}
|
||||
|
||||
public void updatePayTransactionSuccess(Integer payChannel, String params) {
|
||||
payTransactionClient.updatePayTransactionSuccess(payChannel, params);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.iocoder.mall.shopweb.service.product;
|
||||
|
||||
import cn.iocoder.common.framework.enums.CommonStatusEnum;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.productservice.rpc.category.ProductCategoryFeign;
|
||||
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryListQueryReqDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.category.ProductCategoryRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.product.ProductCategoryConvert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Product 分类 Manager
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProductCategoryManager {
|
||||
|
||||
|
||||
@Autowired
|
||||
private ProductCategoryFeign productCategoryFeign;
|
||||
|
||||
public List<ProductCategoryRespVO> listProductCategories(Integer pid) {
|
||||
CommonResult<List<ProductCategoryRespDTO>> listProductCategoriesResult = productCategoryFeign.listProductCategories(
|
||||
new ProductCategoryListQueryReqDTO().setPid(pid).setStatus(CommonStatusEnum.ENABLE.getValue()));
|
||||
listProductCategoriesResult.checkError();
|
||||
return ProductCategoryConvert.INSTANCE.convertList(listProductCategoriesResult.getData());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package cn.iocoder.mall.shopweb.service.product;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.PromotionActivityFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.PriceFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.sku.ProductSkuCalcPriceRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.product.ProductSkuConvert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品 SKU Manager
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProductSkuManager {
|
||||
|
||||
|
||||
@Autowired
|
||||
private PriceFeign priceFeign;
|
||||
@Autowired
|
||||
private PromotionActivityFeign promotionActivityFeign;
|
||||
/**
|
||||
* 计算商品 SKU 价格
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param skuId 商品 SKU 编号
|
||||
* @return SKU 价格明细
|
||||
*/
|
||||
public ProductSkuCalcPriceRespVO calcProductSkuPrice(Integer userId, Integer skuId) {
|
||||
CommonResult<PriceProductCalcRespDTO> calcProductPriceResult = priceFeign.calcProductPrice(new PriceProductCalcReqDTO().setUserId(userId)
|
||||
.setItems(Collections.singletonList(new PriceProductCalcReqDTO.Item(skuId, 1, true))));
|
||||
calcProductPriceResult.checkError();
|
||||
// 拼接结果
|
||||
PriceProductCalcRespDTO.ItemGroup itemGroup = calcProductPriceResult.getData().getItemGroups().get(0);
|
||||
// 1. 加载 满减送 促销活动
|
||||
PromotionActivityRespDTO fullPrivilege = itemGroup.getActivityId() != null ? this.getPromotionActivity(itemGroup.getActivityId()) : null;
|
||||
// 2. 加载 限时折扣 促销活动
|
||||
PriceProductCalcRespDTO.Item item = itemGroup.getItems().get(0);
|
||||
PromotionActivityRespDTO timeLimitedDiscount = item.getActivityId() != null ? this.getPromotionActivity(item.getActivityId()) : null;
|
||||
// 3. 最终组装
|
||||
return ProductSkuConvert.INSTANCE.convert(item, fullPrivilege, timeLimitedDiscount);
|
||||
}
|
||||
|
||||
private PromotionActivityRespDTO getPromotionActivity(Integer activityId) {
|
||||
CommonResult<List<PromotionActivityRespDTO>> listPromotionActivitiesResult = promotionActivityFeign.listPromotionActivities(
|
||||
new PromotionActivityListReqDTO().setActiveIds(Collections.singleton(activityId)));
|
||||
listPromotionActivitiesResult.checkError();
|
||||
return listPromotionActivitiesResult.getData().get(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cn.iocoder.mall.shopweb.service.product;
|
||||
|
||||
import cn.iocoder.common.framework.util.CollectionUtils;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.productservice.enums.spu.ProductSpuDetailFieldEnum;
|
||||
import cn.iocoder.mall.productservice.rpc.category.ProductCategoryFeign;
|
||||
import cn.iocoder.mall.productservice.rpc.category.dto.ProductCategoryRespDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.ProductSpuFeign;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuDetailRespDTO;
|
||||
import cn.iocoder.mall.searchservice.enums.product.SearchProductConditionFieldEnum;
|
||||
import cn.iocoder.mall.searchservice.rpc.product.SearchProductFeign;
|
||||
import cn.iocoder.mall.searchservice.rpc.product.dto.SearchProductConditionReqDTO;
|
||||
import cn.iocoder.mall.searchservice.rpc.product.dto.SearchProductConditionRespDTO;
|
||||
import cn.iocoder.mall.searchservice.rpc.product.dto.SearchProductRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuDetailRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuSearchConditionRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.product.ProductSpuConvert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品 SPU Manager
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProductSpuManager {
|
||||
|
||||
@Autowired
|
||||
private SearchProductFeign searchProductFeign;
|
||||
|
||||
@Autowired
|
||||
private ProductCategoryFeign productCategoryFeign;
|
||||
@Autowired
|
||||
private ProductSpuFeign productSpuFeign;
|
||||
|
||||
public PageResult<ProductSpuRespVO> pageProductSpu(ProductSpuPageReqVO pageReqVO) {
|
||||
CommonResult<PageResult<SearchProductRespDTO>> pageResult =
|
||||
searchProductFeign.pageSearchProduct(ProductSpuConvert.INSTANCE.convert(pageReqVO));
|
||||
pageResult.checkError();
|
||||
return ProductSpuConvert.INSTANCE.convertPage(pageResult.getData());
|
||||
}
|
||||
|
||||
public ProductSpuSearchConditionRespVO getProductSpuSearchCondition(String keyword) {
|
||||
// 获得搜索条件
|
||||
CommonResult<SearchProductConditionRespDTO> getSearchProductConditionResult =
|
||||
searchProductFeign.getSearchProductCondition(new SearchProductConditionReqDTO().setKeyword(keyword)
|
||||
.setFields(Collections.singletonList(SearchProductConditionFieldEnum.CATEGORY.getField())));
|
||||
getSearchProductConditionResult.checkError();
|
||||
// 拼接结果
|
||||
ProductSpuSearchConditionRespVO conditionRespVO = new ProductSpuSearchConditionRespVO();
|
||||
if (CollectionUtils.isEmpty(getSearchProductConditionResult.getData().getCids())) {
|
||||
conditionRespVO.setCategories(Collections.emptyList());
|
||||
} else {
|
||||
CommonResult<List<ProductCategoryRespDTO>> listProductCategoriesResult =
|
||||
productCategoryFeign.listProductCategoriesByIds(getSearchProductConditionResult.getData().getCids());
|
||||
listProductCategoriesResult.checkError();
|
||||
conditionRespVO.setCategories(ProductSpuConvert.INSTANCE.convertList(listProductCategoriesResult.getData()));
|
||||
}
|
||||
return conditionRespVO;
|
||||
}
|
||||
|
||||
public ProductSpuDetailRespVO getProductSpuDetail(Integer id) {
|
||||
CommonResult<ProductSpuDetailRespDTO> getProductSpuDetailResult = productSpuFeign.getProductSpuDetail(id,
|
||||
Arrays.asList(ProductSpuDetailFieldEnum.SKU.getField(), ProductSpuDetailFieldEnum.ATTR.getField()));
|
||||
getProductSpuDetailResult.checkError();
|
||||
return ProductSpuConvert.INSTANCE.convert(getProductSpuDetailResult.getData());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package cn.iocoder.mall.shopweb.service.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.CouponCardFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardCreateReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card.CouponCardPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.card.CouponCardRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.promotion.CouponCardConvert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 优惠劵 Manager
|
||||
*/
|
||||
@Service
|
||||
public class CouponCardManager {
|
||||
|
||||
@Autowired
|
||||
private CouponCardFeign couponCardFeign;
|
||||
/**
|
||||
* 获得优惠劵分页
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param pageVO 优惠劵分页查询
|
||||
* @return 优惠劵分页结果
|
||||
*/
|
||||
public PageResult<CouponCardRespVO> pageCouponCard(Integer userId, CouponCardPageReqVO pageVO) {
|
||||
CommonResult<PageResult<CouponCardRespDTO>> pageCouponCardResult = couponCardFeign.pageCouponCard(
|
||||
CouponCardConvert.INSTANCE.convert(pageVO).setUserId(userId));
|
||||
pageCouponCardResult.checkError();
|
||||
return CouponCardConvert.INSTANCE.convertPage(pageCouponCardResult.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户领取优惠劵
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param couponTemplateId 优惠劵模板编号
|
||||
* @return 优惠劵编号
|
||||
*/
|
||||
public Integer createCouponCard(Integer userId, Integer couponTemplateId) {
|
||||
CommonResult<Integer> createCouponCardResult = couponCardFeign.createCouponCard(
|
||||
new CouponCardCreateReqDTO().setUserId(userId).setCouponTemplateId(couponTemplateId));
|
||||
createCouponCardResult.checkError();
|
||||
return createCouponCardResult.getData();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.mall.shopweb.service.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.CouponTemplateFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.template.CouponTemplateRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.promotion.vo.coupon.template.CouponTemplateRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.promotion.CouponTemplateConvert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 优惠劵(码)模板 Manager
|
||||
*/
|
||||
@Service
|
||||
public class CouponTemplateManager {
|
||||
@Autowired
|
||||
private CouponTemplateFeign couponTemplateFeign;
|
||||
public CouponTemplateRespVO getCouponTemplate(Integer id) {
|
||||
CommonResult<CouponTemplateRespDTO> getCouponTemplateResult = couponTemplateFeign.getCouponTemplate(id);
|
||||
getCouponTemplateResult.checkError();
|
||||
return CouponTemplateConvert.INSTANCE.convert(getCouponTemplateResult.getData());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package cn.iocoder.mall.shopweb.service.promotion;
|
||||
|
||||
import cn.iocoder.common.framework.enums.CommonStatusEnum;
|
||||
import cn.iocoder.common.framework.util.CollectionUtils;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.ProductSpuFeign;
|
||||
import cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.recommend.ProductRecommendFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.recommend.dto.ProductRecommendListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.recommend.dto.ProductRecommendRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.product.vo.product.ProductSpuRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.promotion.ProductRecommendConvert;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品推荐 Manager
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProductRecommendManager {
|
||||
@Autowired
|
||||
private ProductRecommendFeign productRecommendFeign;
|
||||
@Autowired
|
||||
private ProductSpuFeign productSpuFeign;
|
||||
|
||||
public Map<Integer, Collection<ProductSpuRespVO>> listProductRecommends() {
|
||||
// 查询商品推荐列表
|
||||
CommonResult<List<ProductRecommendRespDTO>> listProductRecommendsResult = productRecommendFeign.listProductRecommends(
|
||||
new ProductRecommendListReqDTO().setStatus(CommonStatusEnum.ENABLE.getValue()));
|
||||
listProductRecommendsResult.checkError();
|
||||
listProductRecommendsResult.getData().sort(Comparator.comparing(ProductRecommendRespDTO::getSort)); // 排序,按照 sort 升序
|
||||
// 获得商品集合
|
||||
Map<Integer, ProductSpuRespDTO> spuMap = this.getProductSkuMap(listProductRecommendsResult.getData());
|
||||
// 组合结果,返回
|
||||
Multimap<Integer, ProductSpuRespVO> result = HashMultimap.create();
|
||||
listProductRecommendsResult.getData().forEach(productRecommendBO -> result.put(productRecommendBO.getType(),
|
||||
ProductRecommendConvert.INSTANCE.convert(spuMap.get(productRecommendBO.getProductSpuId()))));
|
||||
return result.asMap();
|
||||
}
|
||||
|
||||
private Map<Integer, ProductSpuRespDTO> getProductSkuMap(List<ProductRecommendRespDTO> productRecommends) {
|
||||
CommonResult<List<ProductSpuRespDTO>> listProductSpusResult = productSpuFeign.listProductSpus(
|
||||
CollectionUtils.convertSet(productRecommends, ProductRecommendRespDTO::getProductSpuId));
|
||||
listProductSpusResult.checkError();
|
||||
return CollectionUtils.convertMap(listProductSpusResult.getData(), ProductSpuRespDTO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package cn.iocoder.mall.shopweb.service.trade;
|
||||
|
||||
import cn.iocoder.common.framework.util.CollectionUtils;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.ProductSkuFeign;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.PromotionActivityFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.PriceFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.cart.CartDetailVO;
|
||||
import cn.iocoder.mall.shopweb.convert.trade.CartConvert;
|
||||
import cn.iocoder.mall.tradeservice.rpc.cart.CartFeign;
|
||||
import cn.iocoder.mall.tradeservice.rpc.cart.dto.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 购物车 Manager
|
||||
*/
|
||||
@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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户的购物车的商品列表
|
||||
*
|
||||
* @return 商品列表
|
||||
*/
|
||||
public CartDetailVO getCartDetail(Integer userId) {
|
||||
// 获得购物车的商品
|
||||
CommonResult<List<CartItemRespDTO>> listCartItemsResult = cartFeign.listCartItems(new CartItemListReqDTO().setUserId(userId));
|
||||
listCartItemsResult.checkError();
|
||||
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
|
||||
if (CollectionUtils.isEmpty(listCartItemsResult.getData())) {
|
||||
CartDetailVO result = new CartDetailVO();
|
||||
result.setItemGroups(Collections.emptyList());
|
||||
result.setFee(new CartDetailVO.Fee(0, 0, 0, 0));
|
||||
return result;
|
||||
}
|
||||
// 计算商品价格
|
||||
CommonResult<PriceProductCalcRespDTO> calcProductPriceResult = priceFeign.calcProductPrice(new PriceProductCalcReqDTO().setUserId(userId)
|
||||
.setItems(listCartItemsResult.getData().stream()
|
||||
.map(cartItem -> new PriceProductCalcReqDTO.Item(cartItem.getSkuId(), cartItem.getQuantity(), cartItem.getSelected()))
|
||||
.collect(Collectors.toList())));
|
||||
calcProductPriceResult.checkError();
|
||||
// 获得促销活动信息
|
||||
Map<Integer, PromotionActivityRespDTO> promotionActivityMap = this.getPromotionActivityMap(calcProductPriceResult.getData());
|
||||
// 获得商品 SKU 信息
|
||||
Map<Integer, ProductSkuRespDTO> productSkuMap = this.getProductSkuMap(listCartItemsResult.getData());
|
||||
// 拼接结果
|
||||
CartDetailVO cartDetailVO = new CartDetailVO();
|
||||
cartDetailVO.setFee(CartConvert.INSTANCE.convert(calcProductPriceResult.getData().getFee()));
|
||||
cartDetailVO.setItemGroups(new ArrayList<>());
|
||||
for (PriceProductCalcRespDTO.ItemGroup itemGroupDTO : calcProductPriceResult.getData().getItemGroups()) {
|
||||
CartDetailVO.ItemGroup itemGroupVO = new CartDetailVO.ItemGroup();
|
||||
cartDetailVO.getItemGroups().add(itemGroupVO);
|
||||
// 活动信息
|
||||
if (itemGroupDTO.getActivityId() != null) {
|
||||
itemGroupVO.setActivity(promotionActivityMap.get(itemGroupDTO.getActivityId()))
|
||||
.setActivityDiscountTotal(itemGroupDTO.getActivityDiscountTotal());
|
||||
}
|
||||
// 商品 SKU 信息
|
||||
itemGroupVO.setItems(new ArrayList<>());
|
||||
itemGroupDTO.getItems().forEach(item -> itemGroupVO.getItems().add(CartConvert.INSTANCE.convert(item,
|
||||
productSkuMap.get(item.getSkuId()), promotionActivityMap.get(item.getActivityId()))));
|
||||
}
|
||||
return cartDetailVO;
|
||||
}
|
||||
|
||||
private Map<Integer, PromotionActivityRespDTO> getPromotionActivityMap(PriceProductCalcRespDTO calcRespDTO) {
|
||||
// 获得所有促销活动编号
|
||||
Set<Integer> activeIds = new HashSet<>();
|
||||
calcRespDTO.getItemGroups().forEach(itemGroup -> {
|
||||
if (itemGroup.getActivityId() != null) {
|
||||
activeIds.add(itemGroup.getActivityId());
|
||||
}
|
||||
itemGroup.getItems().forEach(item -> {
|
||||
if (item.getActivityId() != null) {
|
||||
activeIds.add(item.getActivityId());
|
||||
}
|
||||
});
|
||||
});
|
||||
if (CollectionUtils.isEmpty(activeIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
// 查询促销活动列表
|
||||
CommonResult<List<PromotionActivityRespDTO>> listPromotionActivitiesResult =
|
||||
promotionActivityFeign.listPromotionActivities(new PromotionActivityListReqDTO().setActiveIds(activeIds));
|
||||
listPromotionActivitiesResult.checkError();
|
||||
return CollectionUtils.convertMap(listPromotionActivitiesResult.getData(), PromotionActivityRespDTO::getId);
|
||||
}
|
||||
|
||||
private Map<Integer, ProductSkuRespDTO> getProductSkuMap(List<CartItemRespDTO> itemRespDTOs) {
|
||||
CommonResult<List<ProductSkuRespDTO>> listProductSkusResult = productSkuFeign.listProductSkus(new ProductSkuListQueryReqDTO()
|
||||
.setProductSkuIds(CollectionUtils.convertSet(itemRespDTOs, CartItemRespDTO::getSkuId))
|
||||
.setFields(Arrays.asList(ProductSkuDetailFieldEnum.SPU.getField(), ProductSkuDetailFieldEnum.ATTR.getField())));
|
||||
listProductSkusResult.checkError();
|
||||
return CollectionUtils.convertMap(listProductSkusResult.getData(), ProductSkuRespDTO::getId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package cn.iocoder.mall.shopweb.service.trade;
|
||||
|
||||
import cn.iocoder.common.framework.enums.CommonStatusEnum;
|
||||
import cn.iocoder.common.framework.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.util.CollectionUtils;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.common.framework.vo.PageResult;
|
||||
import cn.iocoder.mall.productservice.enums.sku.ProductSkuDetailFieldEnum;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.ProductSkuFeign;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuListQueryReqDTO;
|
||||
import cn.iocoder.mall.productservice.rpc.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.PromotionActivityFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.activity.dto.PromotionActivityRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.CouponCardFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableListReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.coupon.dto.card.CouponCardAvailableRespDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.PriceFeign;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcReqDTO;
|
||||
import cn.iocoder.mall.promotion.api.rpc.price.dto.PriceProductCalcRespDTO;
|
||||
import cn.iocoder.mall.shopweb.client.trade.TradeOrderClient;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderConfirmCreateInfoRespVO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderCreateReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderPageReqVO;
|
||||
import cn.iocoder.mall.shopweb.controller.trade.vo.order.TradeOrderRespVO;
|
||||
import cn.iocoder.mall.shopweb.convert.trade.CartConvert;
|
||||
import cn.iocoder.mall.shopweb.convert.trade.TradeOrderConvert;
|
||||
import cn.iocoder.mall.tradeservice.enums.order.TradeOrderDetailFieldEnum;
|
||||
import cn.iocoder.mall.tradeservice.rpc.cart.CartFeign;
|
||||
import cn.iocoder.mall.tradeservice.rpc.cart.dto.CartItemListReqDTO;
|
||||
import cn.iocoder.mall.tradeservice.rpc.cart.dto.CartItemRespDTO;
|
||||
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderPageReqDTO;
|
||||
import cn.iocoder.mall.tradeservice.rpc.order.dto.TradeOrderRespDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.mall.shopweb.enums.ShopWebErrorCodeConstants.ORDER_PRODUCT_SKU_NOT_EXISTS;
|
||||
import static cn.iocoder.mall.shopweb.enums.ShopWebErrorCodeConstants.ORDER_PRODUCT_SKU_QUANTITY_NOT_ENOUGH;
|
||||
|
||||
/**
|
||||
* 交易订单 Service
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class TradeOrderService {
|
||||
|
||||
@Autowired
|
||||
private PriceFeign priceFeign;
|
||||
@Autowired
|
||||
private PromotionActivityFeign promotionActivityFeign;
|
||||
|
||||
@Autowired
|
||||
private CartFeign cartFeign;
|
||||
@Autowired
|
||||
private CouponCardFeign couponCardFeign;
|
||||
@Autowired
|
||||
private ProductSkuFeign productSkuFeign;
|
||||
|
||||
@Autowired
|
||||
private TradeOrderClient tradeOrderClient;
|
||||
|
||||
public TradeOrderConfirmCreateInfoRespVO getOrderConfirmCreateInfo(Integer userId, Integer skuId, Integer quantity, Integer couponCardId) {
|
||||
Map<Integer, Integer> skuMap = new HashMap<>();
|
||||
skuMap.put(skuId, quantity);
|
||||
return this.getOrderConfirmCreateInfo0(userId, skuMap, couponCardId);
|
||||
}
|
||||
|
||||
public TradeOrderConfirmCreateInfoRespVO getOrderConfirmCreateInfoFromCart(Integer userId, Integer couponCardId) {
|
||||
// 获得购物车的商品
|
||||
CommonResult<List<CartItemRespDTO>> listCartItemsResult = cartFeign.listCartItems(
|
||||
new CartItemListReqDTO().setUserId(userId).setSelected(true));
|
||||
listCartItemsResult.checkError();
|
||||
// 购物车为空时,构造空的 OrderConfirmCreateInfoRespVO 返回
|
||||
if (CollectionUtils.isEmpty(listCartItemsResult.getData())) {
|
||||
TradeOrderConfirmCreateInfoRespVO result = new TradeOrderConfirmCreateInfoRespVO();
|
||||
result.setItemGroups(Collections.emptyList());
|
||||
result.setFee(new TradeOrderConfirmCreateInfoRespVO.Fee(0, 0, 0, 0));
|
||||
return result;
|
||||
}
|
||||
// 计算商品价格
|
||||
Map<Integer, Integer> skuMap = CollectionUtils.convertMap(listCartItemsResult.getData(),
|
||||
CartItemRespDTO::getSkuId, CartItemRespDTO::getQuantity);
|
||||
return this.getOrderConfirmCreateInfo0(userId, skuMap, couponCardId);
|
||||
}
|
||||
|
||||
private TradeOrderConfirmCreateInfoRespVO getOrderConfirmCreateInfo0(Integer userId, Map<Integer, Integer> skuMap, Integer couponCardId) {
|
||||
// 校验商品都存在,并且库存足够
|
||||
this.checkProductSkus(skuMap);
|
||||
// 获得商品 SKU 信息
|
||||
Map<Integer, ProductSkuRespDTO> productSkuMap = this.checkProductSkus(skuMap);
|
||||
// 计算商品价格
|
||||
CommonResult<PriceProductCalcRespDTO> calcProductPriceResult = priceFeign.calcProductPrice(new PriceProductCalcReqDTO()
|
||||
.setUserId(userId).setCouponCardId(couponCardId)
|
||||
.setItems(skuMap.entrySet().stream().map(entry -> new PriceProductCalcReqDTO.Item(entry.getKey(), entry.getValue(), true))
|
||||
.collect(Collectors.toList())));
|
||||
calcProductPriceResult.checkError();
|
||||
// 获得促销活动信息
|
||||
Map<Integer, PromotionActivityRespDTO> promotionActivityMap = this.getPromotionActivityMap(calcProductPriceResult.getData());
|
||||
// 拼接结果
|
||||
TradeOrderConfirmCreateInfoRespVO createInfoRespVO = new TradeOrderConfirmCreateInfoRespVO();
|
||||
createInfoRespVO.setFee(TradeOrderConvert.INSTANCE.convert(calcProductPriceResult.getData().getFee()));
|
||||
createInfoRespVO.setItemGroups(new ArrayList<>(calcProductPriceResult.getData().getItemGroups().size()));
|
||||
for (PriceProductCalcRespDTO.ItemGroup itemGroupDTO : calcProductPriceResult.getData().getItemGroups()) {
|
||||
TradeOrderConfirmCreateInfoRespVO.ItemGroup itemGroupVO = new TradeOrderConfirmCreateInfoRespVO.ItemGroup();
|
||||
createInfoRespVO.getItemGroups().add(itemGroupVO);
|
||||
// 活动信息
|
||||
if (itemGroupDTO.getActivityId() != null) {
|
||||
itemGroupVO.setActivity(promotionActivityMap.get(itemGroupDTO.getActivityId()))
|
||||
.setActivityDiscountTotal(itemGroupDTO.getActivityDiscountTotal());
|
||||
}
|
||||
// 商品 SKU 信息
|
||||
itemGroupVO.setItems(new ArrayList<>());
|
||||
itemGroupDTO.getItems().forEach(item -> itemGroupVO.getItems().add(CartConvert.INSTANCE.convert(item,
|
||||
productSkuMap.get(item.getSkuId()), promotionActivityMap.get(item.getActivityId()))));
|
||||
}
|
||||
// 查询可用优惠劵信息
|
||||
CommonResult<List<CouponCardAvailableRespDTO>> listAvailableCouponCardsResult = couponCardFeign.listAvailableCouponCards(
|
||||
new CouponCardAvailableListReqDTO().setUserId(userId)
|
||||
.setItems(TradeOrderConvert.INSTANCE.convertList(calcProductPriceResult.getData().getItemGroups())));
|
||||
listAvailableCouponCardsResult.checkError();
|
||||
createInfoRespVO.setCouponCards(listAvailableCouponCardsResult.getData());
|
||||
return createInfoRespVO;
|
||||
}
|
||||
|
||||
private Map<Integer, ProductSkuRespDTO> checkProductSkus(Map<Integer, Integer> skuMap) {
|
||||
// 获得商品 SKU 列表
|
||||
CommonResult<List<ProductSkuRespDTO>> listProductSkusResult = productSkuFeign.listProductSkus(new ProductSkuListQueryReqDTO()
|
||||
.setProductSkuIds(skuMap.keySet())
|
||||
.setFields(Arrays.asList(ProductSkuDetailFieldEnum.SPU.getField(), ProductSkuDetailFieldEnum.ATTR.getField())));
|
||||
listProductSkusResult.checkError();
|
||||
Map<Integer, ProductSkuRespDTO> productSkuMap = CollectionUtils.convertMap(listProductSkusResult.getData(), ProductSkuRespDTO::getId);
|
||||
// 校验商品 SKU 是否合法
|
||||
for (Map.Entry<Integer, Integer> entry : skuMap.entrySet()) {
|
||||
ProductSkuRespDTO productSku = productSkuMap.get(entry.getKey());
|
||||
if (productSku == null || !CommonStatusEnum.ENABLE.getValue().equals(productSku.getStatus())) {
|
||||
throw ServiceExceptionUtil.exception(ORDER_PRODUCT_SKU_NOT_EXISTS);
|
||||
}
|
||||
if (productSku.getQuantity() < entry.getValue()) {
|
||||
throw ServiceExceptionUtil.exception(ORDER_PRODUCT_SKU_QUANTITY_NOT_ENOUGH);
|
||||
}
|
||||
}
|
||||
return productSkuMap;
|
||||
}
|
||||
|
||||
private Map<Integer, PromotionActivityRespDTO> getPromotionActivityMap(PriceProductCalcRespDTO calcRespDTO) {
|
||||
// 获得所有促销活动编号
|
||||
Set<Integer> activeIds = new HashSet<>();
|
||||
calcRespDTO.getItemGroups().forEach(itemGroup -> {
|
||||
if (itemGroup.getActivityId() != null) {
|
||||
activeIds.add(itemGroup.getActivityId());
|
||||
}
|
||||
itemGroup.getItems().forEach(item -> {
|
||||
if (item.getActivityId() != null) {
|
||||
activeIds.add(item.getActivityId());
|
||||
}
|
||||
});
|
||||
});
|
||||
if (CollectionUtils.isEmpty(activeIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
// 查询促销活动列表
|
||||
CommonResult<List<PromotionActivityRespDTO>> listPromotionActivitiesResult =
|
||||
promotionActivityFeign.listPromotionActivities(new PromotionActivityListReqDTO().setActiveIds(activeIds));
|
||||
listPromotionActivitiesResult.checkError();
|
||||
return CollectionUtils.convertMap(listPromotionActivitiesResult.getData(), PromotionActivityRespDTO::getId);
|
||||
}
|
||||
|
||||
public Integer createTradeOrder(Integer userId, String ip, TradeOrderCreateReqVO createReqVO) {
|
||||
return tradeOrderClient.createTradeOrder(TradeOrderConvert.INSTANCE.convert(createReqVO)
|
||||
.setUserId(userId).setIp(ip));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得交易订单
|
||||
*
|
||||
* @param tradeOrderId 交易订单编号
|
||||
* @return 交易订单
|
||||
*/
|
||||
public TradeOrderRespVO getTradeOrder(Integer tradeOrderId) {
|
||||
return TradeOrderConvert.INSTANCE.convert(tradeOrderClient.getTradeOrder(tradeOrderId,
|
||||
TradeOrderDetailFieldEnum.ITEM.getField()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得交易订单分页
|
||||
*
|
||||
* @param pageVO 订单交易分页查询
|
||||
* @return 订单交易分页结果
|
||||
*/
|
||||
public PageResult<TradeOrderRespVO> pageTradeOrder(Integer userId, TradeOrderPageReqVO pageVO) {
|
||||
PageResult<TradeOrderRespDTO> pageTradeOrderResult = tradeOrderClient.pageTradeOrder(
|
||||
TradeOrderConvert.INSTANCE.convert(pageVO).setUserId(userId)
|
||||
.setFields(Collections.singleton(TradeOrderDetailFieldEnum.ITEM.getField()))
|
||||
.setSorts(Collections.singletonList(TradeOrderPageReqDTO.ID_DESC)));
|
||||
return TradeOrderConvert.INSTANCE.convertPage(pageTradeOrderResult);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
15
归档/shop-web-app/src/main/resources/application-dev.yml
Normal file
15
归档/shop-web-app/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
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 服务注册中心的地址
|
||||
18
归档/shop-web-app/src/main/resources/application-local.yml
Normal file
18
归档/shop-web-app/src/main/resources/application-local.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
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 服务注册中心的地址
|
||||
75
归档/shop-web-app/src/main/resources/application.yml
Normal file
75
归档/shop-web-app/src/main/resources/application.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
# 服务器的配置项
|
||||
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: '*' # 暴露所有监控端点
|
||||
Reference in New Issue
Block a user