后端:删除购物车模块,合并到订单模块

后端:设计订单价格计算相关方法
This commit is contained in:
YunaiV 2019-04-09 23:39:38 +08:00
parent 6eda8734a6
commit 3e485c2d0f
32 changed files with 535 additions and 413 deletions

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cart</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cart-application</artifactId>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>user-sdk</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -1,13 +0,0 @@
package cn.iocoder.mall.cart.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.cart"})
public class CartApplication {
public static void main(String[] args) {
SpringApplication.run(CartApplication.class, args);
}
}

View File

@ -1,42 +0,0 @@
package cn.iocoder.mall.cart.application.config;
import cn.iocoder.common.framework.config.GlobalExceptionHandler;
import cn.iocoder.common.framework.servlet.CorsFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.*;
@EnableWebMvc
@Configuration
@Import(value = {GlobalExceptionHandler.class}) // 统一全局返回
public class MVCConfiguration implements WebMvcConfigurer {
// @Autowired
// private SecurityInterceptor securityInterceptor;
// @Reference
// private OAuth2Service oauth2Service;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(securityInterceptor);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 解决 swagger-ui.html 的访问参考自 https://stackoverflow.com/questions/43545540/swagger-ui-no-mapping-found-for-http-request 解决
registry.addResourceHandler("swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
registry.addResourceHandler("webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new CorsFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}

View File

@ -1,36 +0,0 @@
package cn.iocoder.mall.cart.application.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.biz.application.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("购物车子系统")
.description("购物车子系统")
.termsOfServiceUrl("http://www.iocoder.cn")
.version("1.0.0")
.build();
}
}

View File

@ -1,9 +0,0 @@
spring:
application:
name: cart-application
# server
server:
port: 18086
servlet:
context-path: /cart-api/

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cart</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cart-service-api</artifactId>
<dependencies>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,4 +0,0 @@
package cn.iocoder.mall.cart.api;
public interface CartService {
}

View File

@ -1,28 +0,0 @@
package cn.iocoder.mall.cart.api.constant;
/**
* 错误码枚举类
*
* 购物车系统使用 1-005-000-000
*/
public enum CartErrorCodeEnum {
;
private final int code;
private final String message;
CartErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cart</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cart-service-impl</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>cart-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 提供给 mapstruct 使用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,14 +0,0 @@
package cn.iocoder.mall.cart.biz.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@MapperScan("cn.iocoder.mall.cart.biz.dao") // 扫描对应的 Mapper 接口
@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理为什么使用 proxyTargetClass 参数参见 https://blog.csdn.net/huang_550/article/details/76492600
public class DatabaseConfiguration {
// 数据源使用 HikariCP
}

View File

@ -1,19 +0,0 @@
package cn.iocoder.mall.cart.biz.config;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.mall.cart.api.constant.CartErrorCodeEnum;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
@Configuration
public class ServiceExceptionConfiguration {
@EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html
public void initMessages() {
for (CartErrorCodeEnum item : CartErrorCodeEnum.values()) {
ServiceExceptionUtil.put(item.getCode(), item.getMessage());
}
}
}

View File

@ -1 +0,0 @@
package cn.iocoder.mall.cart.biz;

View File

@ -1,44 +0,0 @@
spring:
# datasource
datasource:
url: jdbc:mysql://180.167.213.26:13306/mall_cart?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: ${MALL_MYSQL_PASSWORD}
# mybatis
mybatis:
config-location: classpath:mybatis-config.xml
mapper-locations: classpath:mapper/*.xml
type-aliases-package: cn.iocoder.mall.cart.biz.dataobject
# dubbo
dubbo:
application:
name: cart-service
registry:
address: zookeeper://127.0.0.1:2181
protocol:
port: -1
name: dubbo
scan:
base-packages: cn.iocoder.mall.cart.biz.service
# xxl-job
#xxl:
# job:
# admin:
# addresses: http://127.0.0.1:8080/xxl-job-admin
# executor:
# appname: cart-job-executor
# ip:
# port: 0
# logpath: /Users/yunai/logs/xxl-job/
# logretentiondays: 1
# accessToken:
# rocketmq
#rocketmq:
# name-server: 127.0.0.1:9876
# producer:
# group: cart-producer-group

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mall-parent</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cart</artifactId>
<packaging>pom</packaging>
<modules>
<module>cart-application</module>
<module>cart-service-api</module>
<module>cart-service-impl</module>
</modules>
</project>

View File

@ -0,0 +1,22 @@
package cn.iocoder.mall.order.application.controller.users;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.order.api.CartService;
import cn.iocoder.mall.order.api.OrderService;
public class UsersCartController {
// TODO 注入
private CartService cartService;
// TODO 注入
private OrderService orderService;
public CommonResult<Object> confirmOrder() {
// 查询购物车列表选中的
// cartService.list(userId, true);
// 查询确认订单信息的明细
return null;
}
}

View File

@ -6,7 +6,6 @@ import cn.iocoder.mall.order.api.bo.OrderCreateBO;
import cn.iocoder.mall.order.api.bo.OrderPageBO;
import cn.iocoder.mall.order.api.dto.OrderCreateDTO;
import cn.iocoder.mall.order.api.dto.OrderQueryDTO;
import cn.iocoder.mall.order.api.dto.OrderUserPageDTO;
import cn.iocoder.mall.order.application.convert.OrderConvertAPP;
import cn.iocoder.mall.order.application.po.user.OrderCreatePO;
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;

View File

@ -0,0 +1,26 @@
package cn.iocoder.mall.order.application.vo;
public class FeeMessageVO {
/**
* 总价
*/
private Integer originalTotal;
/**
* 优惠总价
*
* 注意满多少元包邮不算在优惠中
*/
private Integer discountTotal;
/**
* 邮费
*/
private Integer postageTotal;
/**
* 最终价格
*
* 计算公式 = 总价 - 优惠总价 + 邮费
*/
private Integer presentTotal;
}

View File

@ -0,0 +1,5 @@
package cn.iocoder.mall.order.application.vo;
public class UsersCartItemVO {
}

View File

@ -0,0 +1,11 @@
package cn.iocoder.mall.order.application.vo;
import java.util.List;
public class UsersCartListVO {
private List<UsersCartItemVO> items;
private FeeMessageVO feeMessage;
}

View File

@ -0,0 +1,99 @@
package cn.iocoder.mall.order.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.order.api.bo.CartBO;
import cn.iocoder.mall.order.api.bo.CartItemBO;
import cn.iocoder.mall.order.api.bo.OrderCreateBO;
import org.springframework.lang.Nullable;
import java.util.List;
public interface CartService {
// ========== 购物车 Item 的逻辑 ==========
/**
* 添加商品至购物车
*
* @param userId 用户编号
* @param skuId 商品 SKU 编号
* @param quantity 数量
* @return 是否成功
*/
CommonResult<Boolean> add(Integer userId, Integer skuId, Integer quantity);
/**
* 购物车更新商品数量
*
* @param userId 用户编号
* @param skuId 商品 SKU 编号
* @param quantity 数量
* @return 是否成功
*/
CommonResult<Boolean> updateQuantity(Integer userId, Integer skuId, Integer quantity);
/**
* 购物车更新商品是否选中
*
* @param userId 用户编号
* @param skuId 商品 SKU 编号
* @return 是否成功
*/
CommonResult<Boolean> updateSelected(Integer userId, Integer skuId);
/**
* 购物车删除商品
*
* @param userId 用户编号
* @param skuIds 商品 SKU 编号的数组
*
* @return 是否成功
*/
CommonResult<Boolean> delete(Integer userId, List<Integer> skuIds);
/**
* 清空购物车
*
* @param userId 用户编号
* @return 是否成功
*/
CommonResult<Boolean> deleteAll(Integer userId);
/**
* 查询用户在购物车中的商品数量
*
* @param userId 用户编号
* @return 商品数量
*/
CommonResult<Integer> count(Integer userId, String nobody, Integer shopId);
/**
* 显示买家购物车中的商品列表并根据 selected 进行过滤
*
* @param userId 用户编号
* @param selected 是否选中若为空则不进行筛选
* @return 购物车中商品列表信息
*/
List<CartItemBO> list(Integer userId, @Nullable Boolean selected);
// ========== 购物车与订单相关的逻辑 ==========
/**
* 获得购物车明细
*
* TODO 芋艿可能放在 Controller 更合适
*
* @param userId 用户编号
* @return 购物车明细
*/
CommonResult<CartBO> details(Integer userId);
/**
* 基于购物车创建订单
*
* @param userId 用户编号
* @return 订单信息
*/
CommonResult<OrderCreateBO> createOrder(Integer userId);
}

View File

@ -1,10 +1,7 @@
package cn.iocoder.mall.order.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.order.api.bo.OrderCreateBO;
import cn.iocoder.mall.order.api.bo.OrderItemBO;
import cn.iocoder.mall.order.api.bo.OrderPageBO;
import cn.iocoder.mall.order.api.bo.OrderRecipientBO;
import cn.iocoder.mall.order.api.bo.*;
import cn.iocoder.mall.order.api.dto.*;
import java.util.List;
@ -41,6 +38,14 @@ public interface OrderService {
*/
CommonResult<OrderRecipientBO> getOrderRecipientBO(Integer orderId);
/**
* 计算订单金额返回计算结果
*
* @param calcOrderPriceDTO 计算订单金额 DTO
* @return 计算订单金额结果
*/
CalcOrderPriceBO calcOrderPrice(CalcOrderPriceDTO calcOrderPriceDTO);
/**
* 订单 - 创建
*

View File

@ -0,0 +1,99 @@
package cn.iocoder.mall.order.api.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 计算订单价格结果 BO
*/
@Data
@Accessors(chain = true)
public class CalcOrderPriceBO {
/**
* 商品分组数组
*/
private List<ItemGroup> itemGroups;
/**
* 邮费信息
*/
private Postage postage;
/**
* 费用
*/
private Fee fee;
/**
* 商品分组
*
* 多个商品参加同一个活动从而形成分组
*/
@Data
@Accessors(chain = true)
public static class ItemGroup {
// TODO 优惠活动
private Object activity;
/**
* 商品数组
*/
private List<Item> items;
}
@Data
@Accessors(chain = true)
public static class Item {
// TODO 信息要相当完整
}
/**
* 费用合计
*/
@Data
@Accessors(chain = true)
public static class Fee {
/**
* 总价
*/
private Integer originalTotal;
/**
* 优惠总价
*
* 注意满多少元包邮不算在优惠中
*/
private Integer discountTotal;
/**
* 邮费
*/
private Integer postageTotal;
/**
* 最终价格
*
* 计算公式 = 总价 - 优惠总价 + 邮费
*/
private Integer presentTotal;
}
/**
* 邮费信息
*/
@Data
@Accessors(chain = true)
public static class Postage {
/**
* 需要满足多少钱可以包邮单位
*/
private Integer threshold;
}
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.mall.order.api.bo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 购物车明细 BO
*/
@Data
@Accessors(chain = true)
public class CartBO {
/**
* 商品分组数组
*/
private List<CartItemGroupBO> itemGroups;
/**
* 费用
*/
private FeeMessageBO fee;
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.mall.order.api.bo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 购物车的商品信息 DO
*/
@Data
@Accessors(chain = true)
public class CartItemBO {
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.mall.order.api.bo;
import java.util.List;
/**
* 商品分组 BO
*
* 主要目的是多个商品
*/
public class CartItemGroupBO {
/**
* TODO 芋艿活动
*/
private Object activity;
/**
* 商品数组
*/
private List<CartItemBO> items;
}

View File

@ -0,0 +1,4 @@
package cn.iocoder.mall.order.api.bo;
public class FeeDetailBO {
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.mall.order.api.bo;
public class FeeMessageBO {
/**
* 总价
*/
private Integer originalTotal;
/**
* 优惠总价
*
* 注意满多少元包邮不算在优惠中
*/
private Integer discountTotal;
/**
* 邮费
*/
private Integer postageTotal;
/**
* 最终价格
*
* 计算公式 = 总价 - 优惠总价 + 邮费
*/
private Integer presentTotal;
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.mall.order.api.bo;
import java.util.List;
/**
* 商家商品分组
*/
public class MerchantItemGroup {
/**
* 商品分组数组
*/
private List<CartItemGroupBO> itemGroups;
/**
* 运费详情
*/
private PostageDetailBO postageDetail;
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.mall.order.api.bo;
public class PostageDetailBO {
// "description": "有品甄选商品即有品配送和第三方商家发货的商品2018年1月1日起单笔订单满99元免运费不满99元收10元运费。",
// "leftTotal": "0.00",
// "merchantName": "有品配送",
// "postFee": "0.00",
// "postage": "10.00",
// "postageType": 0,
// "selCount": 14,
// "threshold": "99.00"
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.mall.order.api.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 计算订单价格 DTO
*/
@Data
@Accessors(chain = true)
public class CalcOrderPriceDTO {
/**
* 商品数组
*/
private List<Integer> items;
@Data
@Accessors(chain = true)
private static class Item {
/**
* SKU 编号
*/
private Integer skuId;
/**
* 数量
*/
private Integer quantity;
/**
* 是否选中
*
* 注意下目前只有在购物车的时候才可能出现该属性为 false 其它情况下都会为 true 为主
*/
private Boolean selected;
}
}

View File

@ -0,0 +1,100 @@
package cn.iocoder.mall.order.biz.dataobject;
import cn.iocoder.common.framework.dataobject.BaseDO;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 购物车的商品信息
*/
@Data
@Accessors(chain = true)
public class CartItemDO extends BaseDO {
// ========= 基础字段 BEGIN =========
/**
* 编号唯一自增
*/
private Integer id;
/**
* 状态
*
* 1-正常
* 2-主动删除
* 3-下单删除
*/
private Integer status;
/**
* 商品在购物车中的删除时间
*/
private Date deleteTime;
/**
* 是否选中
*/
private Boolean selected;
// ========= 基础字段 END =========
// ========= 买家信息 BEGIN =========
/**
* 用户编号
*/
private Integer userId;
// /**
// * 会话 key
// */
// private String nobody;
// ========= 买家信息 END =========
// ========= 商品信息 BEGIN =========
/**
* 商品 SPU 编号
*/
private Integer spuId;
/**
* 商品 SKU 编号
*/
private Integer skuId;
/**
* 商品购买数量
*/
private Integer quantity;
// TODO 冗余字段
// ========= 商品信息 END =========
// ========= 交易信息 BEGIN =========
/**
* 订单编号
*/
private String orderId;
/**
* 订单创建时间
*/
private Date orderCreateTime;
// ========= 交易信息 BEGIN =========
// ========= 优惠信息 BEGIN =========
// /**
// * 商品营销活动编号
// */
// private Integer activityId;
// /**
// * 商品营销活动类型
// */
// private Integer activityType;
// ========= 优惠信息 END =========
}

View File

@ -22,7 +22,6 @@
<module>ops</module>
<module>pay</module>
<module>promotion</module>
<module>cart</module>
</modules>
<packaging>pom</packaging>