diff --git a/mall-oms/oms-boot/pom.xml b/mall-oms/oms-boot/pom.xml new file mode 100644 index 000000000..aa074443e --- /dev/null +++ b/mall-oms/oms-boot/pom.xml @@ -0,0 +1,168 @@ + + + + mall-oms + com.youlai + 1.0.0 + + 4.0.0 + + oms-boot + + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + + + + com.youlai + oms-api + ${youlai.version} + + + + com.youlai + pms-api + ${youlai.version} + + + + com.youlai + common-mybatis + ${youlai.version} + + + + com.youlai + common-web + ${youlai.version} + + + + com.youlai + common-redis + ${youlai.version} + + + + com.youlai + common-rabbitmq + ${youlai.version} + + + + org.springframework.boot + spring-boot-starter-web + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + org.springframework.boot + spring-boot-configuration-processor + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-seata + + + + io.seata + seata-all + + + io.seata + seata-spring-boot-starter + + + + + + io.seata + seata-all + + + + io.seata + seata-spring-boot-starter + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + com.spotify + docker-maven-plugin + 1.0.0 + + + + + + + + ${project.artifactId} + + + latest + + + openjdk:8-jdk-alpine + + + / + + ["java","-jar","${project.build.finalName}.jar"] + + + https://b.youlai.store:2376 + + C:\cert\docker\b.youlai.store + + + + + / + + ${project.build.directory} + + ${project.build.finalName}.jar + + + + + + + + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/OmsApplication.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/OmsApplication.java new file mode 100644 index 000000000..1b8c8a3e1 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/OmsApplication.java @@ -0,0 +1,24 @@ +package com.youlai.mall; + + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.amqp.rabbit.annotation.EnableRabbit; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) +@EnableDiscoveryClient +@EnableFeignClients +//@EnableConfigurationProperties({ThreadPoolProperties.class}) +@MapperScan({"com.youlai.mall.oms.mapper", "com.youlai.mall.oms.dao"}) +@EnableRabbit +public class OmsApplication { + + public static void main(String[] args) { + SpringApplication.run(OmsApplication.class); + } + +} diff --git a/youlai-common/common-redis/src/main/java/com/youlai/common/redis/constant/RedisKeyConstants.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/common/RedisConstants.java similarity index 73% rename from youlai-common/common-redis/src/main/java/com/youlai/common/redis/constant/RedisKeyConstants.java rename to mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/common/RedisConstants.java index 6ea6e2163..243c23674 100644 --- a/youlai-common/common-redis/src/main/java/com/youlai/common/redis/constant/RedisKeyConstants.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/common/RedisConstants.java @@ -1,6 +1,6 @@ -package com.youlai.common.redis.constant; +package com.youlai.mall.oms.common; -public interface RedisKeyConstants { +public interface RedisConstants { Long REDIS_KEY_TIME_OUT = 3600 * 24L; diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/SwaggerConfiguration.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/SwaggerConfiguration.java new file mode 100644 index 000000000..3f35f6273 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/SwaggerConfiguration.java @@ -0,0 +1,78 @@ +package com.youlai.mall.oms.config; + +import com.google.common.collect.Lists; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.annotation.Order; +import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.OAuthBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author haoxr + * @Date 2021-02-25 15:36 + * @Version 1.0.0 + */ +@Configuration +@EnableSwagger2WebMvc +@Import(BeanValidatorPluginsConfiguration.class) +public class SwaggerConfiguration { + + @Bean + public Docket restApi() { + //schema + List grantTypes=new ArrayList<>(); + //密码模式 + String passwordTokenUrl="http://localhost:9999/youlai-auth/oauth/token"; + ResourceOwnerPasswordCredentialsGrant resourceOwnerPasswordCredentialsGrant=new ResourceOwnerPasswordCredentialsGrant(passwordTokenUrl); + grantTypes.add(resourceOwnerPasswordCredentialsGrant); + OAuth oAuth=new OAuthBuilder().name("oauth2") + .grantTypes(grantTypes).build(); + //context + //scope方位 + List scopes=new ArrayList<>(); + scopes.add(new AuthorizationScope("read","read resources")); + scopes.add(new AuthorizationScope("write","write resources")); + scopes.add(new AuthorizationScope("reads","read all resources")); + scopes.add(new AuthorizationScope("writes","write all resources")); + + SecurityReference securityReference=new SecurityReference("oauth2",scopes.toArray(new AuthorizationScope[]{})); + SecurityContext securityContext=new SecurityContext(Lists.newArrayList(securityReference),PathSelectors.ant("/**")); + //schemas + List securitySchemes=Lists.newArrayList(oAuth); + //securyContext + List securityContexts=Lists.newArrayList(securityContext); + return new Docket(DocumentationType.SWAGGER_2) + .select() + .apis(RequestHandlerSelectors.basePackage("com.youlai.mall.oms.controller")) + .paths(PathSelectors.any()) + .build() + .securityContexts(securityContexts) + .securitySchemes(securitySchemes) + .apiInfo(apiInfo()); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("订单中心REST接口") + .description("
订单提交、秒杀接口
") + .termsOfServiceUrl("https://www.youlai.store") + .contact(new Contact("yl", "https://github.com/hxrui", "1490493387@qq.com")) + .license("Open Source") + .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0") + .version("1.0.0") + .build(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/rabbitmq/OmsRabbitConfig.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/rabbitmq/OmsRabbitConfig.java new file mode 100644 index 000000000..b4e410129 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/rabbitmq/OmsRabbitConfig.java @@ -0,0 +1,145 @@ +package com.youlai.mall.oms.config.rabbitmq; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author huawei + * @desc rabbitmq 业务相关配置类 + * 订单相关业务统一使用 order-event-exchange 交换机 + * order.delay.queue 队列,用于存放需要延时多长时间处理的订单,不需要被消费 + * order.release.queue 队列,用于真正执行处理订单,需要被业务消费,如果订单还没有付款需要自动关闭订单并释放库存 + *

+ * order.create.order 建立交换机与 order.delay.queue 队列的绑定关系,目的是将新创建的订单放入延时队列中 + * order.release.order 建立交换机与 order.release.queue 队列的绑定关系,目的是将延时队列中到达延时时间的订单执行释放操作 + *

+ * 自动创建相关 交换机,队列,路由键 + * @email huawei_code@163.com + * @date 2021/1/17 + */ +@Configuration +@Slf4j +public class OmsRabbitConfig { + + @Autowired + private RabbitTemplate rabbitTemplate; + + /** + * 订单死信-延时队列 + * + * @return + */ + @Bean + public Queue orderDelayQueue() { + Map args = new HashMap<>(); + args.put("x-dead-letter-exchange", OmsRabbitConstants.ORDER_EVENT_EXCHANGE); + args.put("x-dead-letter-routing-key", OmsRabbitConstants.ORDER_RELEASE_ORDER_KEY); + args.put("x-message-ttl", 60000); + Queue queue = new Queue(OmsRabbitConstants.ORDER_DELAY_QUEUE, true, false, false, args); + + return queue; + + } + + /** + * 释放订单队列 + * 订单系统从该队列中取出订单order,判断是否超时未支付 + * + * @return + */ + @Bean + public Queue orderReleaseQueue() { + return new Queue(OmsRabbitConstants.ORDER_RELEASE_QUEUE, true, false, false); + } + + /** + * Topic类型 订单交换机 + * @return + */ + @Bean + public Exchange orderEventExchange() { + return new TopicExchange(OmsRabbitConstants.ORDER_EVENT_EXCHANGE, true, false); + } + + /** + * 建立 order.delay.queue 队列与交换机绑定 + * @return + */ + @Bean + public Binding orderCreateOrderBinding() { + //String destination, DestinationType destinationType, String exchange, String routingKey, + // @Nullable Map arguments + return new Binding(OmsRabbitConstants.ORDER_DELAY_QUEUE, Binding.DestinationType.QUEUE, OmsRabbitConstants.ORDER_EVENT_EXCHANGE, OmsRabbitConstants.ORDER_CREATE_ORDER_KEY, null); + } + + /** + * 建立 order.release.queue 与交换机绑定 + * @return + */ + @Bean + public Binding orderReleaseOrderBinding() { + return new Binding(OmsRabbitConstants.ORDER_RELEASE_QUEUE, Binding.DestinationType.QUEUE, OmsRabbitConstants.ORDER_EVENT_EXCHANGE, OmsRabbitConstants.ORDER_RELEASE_ORDER_KEY, null); + + } + + /** + * 生产者投递消息后,如果Broker收到消息后,会给生产者一个ACK。生产者通过ACK,可以确认这条消息是否正常发送到Broker,这种方式是消息可靠性投递的核心 + * 步骤1:yaml文件中添加配置 spring.rabbitmq.publisher-confirm-type: correlated + * 步骤2:编写代码 + */ + @PostConstruct + public void setConfirmCallback() { + + rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() { + + /** + * @param correlationData 发送消息时指定的唯一关联数据(消息id) + * @param ack 投递结果 + * @param cause 失败原因 + */ + @Override + public void confirm(CorrelationData correlationData, boolean ack, String cause) { + if (ack) { + log.info("消息投递到交换机成功:[correlationData={}]", correlationData); + } else { + log.error("消息投递到交换机成功:[correlationData={},原因={}]", correlationData, cause); + } + + //TODO 根据ACK状态做对应的消息更新操作 + } + }); + } + + /** + * + * 注意下面两项必须同时配置 + * # 开启阶段二(消息从E->Q)的确认回调 Exchange --> Queue returnCallback + * spring.rabbitmq.publisher-returns=true + * + * #为true,则交换机处理消息到路由失败,则会返回给生产者 + * spring.rabbitmq.template.mandatory=true + */ + @PostConstruct + public void setQueueCallback() { + rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() { + + @Override + public void returnedMessage(ReturnedMessage returnedMessage) { + log.error("路由到队列失败,[消息内容:{},交换机:{},路由件:{},回复码:{},回复文本:{}]", + returnedMessage.getMessage(), returnedMessage.getExchange(), + returnedMessage.getRoutingKey(), returnedMessage.getReplyCode(), returnedMessage.getReplyText()); + + } + }); + } +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/rabbitmq/OmsRabbitConstants.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/rabbitmq/OmsRabbitConstants.java new file mode 100644 index 000000000..f111627b9 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/rabbitmq/OmsRabbitConstants.java @@ -0,0 +1,22 @@ +package com.youlai.mall.oms.config.rabbitmq; + +/** + * @author huawei + * @desc RabbitMQ 相关常量 + * @email huawei_code@163.com + * @date 2021/1/17 + */ +public class OmsRabbitConstants { + + public static final String ORDER_EVENT_EXCHANGE = "order_event_exchange"; + + public static final String ORDER_DELAY_QUEUE = "order.delay.queue"; + + public static final String ORDER_RELEASE_QUEUE = "order.release.queue"; + + public static final String ORDER_CREATE_ORDER_KEY = "order.create.order"; + + public static final String ORDER_RELEASE_ORDER_KEY = "order.release.order"; + + public static final Integer ORDER_RELEASE_TTL = 60000; +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/thread/AsyncConfig.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/thread/AsyncConfig.java new file mode 100644 index 000000000..1f919a7f9 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/thread/AsyncConfig.java @@ -0,0 +1,42 @@ +//package com.youlai.mall.oms.config.thread; +// +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.core.task.AsyncTaskExecutor; +//import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +// +//import java.util.concurrent.ThreadPoolExecutor; +// +///** +// * @author huawei +// * @desc 异步任务线程配置 +// * @email huawei_code@163.com +// * @date 2021/1/16 +// */ +//@Configuration +//@Slf4j +//public class AsyncConfig { +// +// @Bean("asyncTaskExecutor") +// public AsyncTaskExecutor asyncTaskExecutor(ThreadPoolProperties properties) { +// log.info("loading asyncTaskExecutor ..."); +// ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); +// //配置核心线程数 +// executor.setCorePoolSize(properties.getCorePoolSize()); +// //配置最大线程数 +// executor.setMaxPoolSize(properties.getMaxPoolSize()); +// //配置队列大小 +// executor.setQueueCapacity(properties.getQueueCapacity()); +// executor.setKeepAliveSeconds(properties.getKeepAliveSeconds()); +// //配置线程池中的线程的名称前缀 +// executor.setThreadNamePrefix("async-service-"); +// +// // 设置拒绝策略:当pool已经达到max size的时候,如何处理新任务 +// // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 +// executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); +// //执行初始化 +// executor.initialize(); +// return executor; +// } +//} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/thread/ThreadPoolProperties.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/thread/ThreadPoolProperties.java new file mode 100644 index 000000000..8bd7fff92 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/thread/ThreadPoolProperties.java @@ -0,0 +1,23 @@ +//package com.youlai.mall.oms.config.thread; +// +//import lombok.Data; +//import org.springframework.boot.context.properties.ConfigurationProperties; +// +///** +// * @author huawei +// * @desc 线程池配置属性类 +// * @email huawei_code@163.com +// * @date 2021/1/16 +// */ +//@Data +//@ConfigurationProperties(prefix = "task.pool") +//public class ThreadPoolProperties { +// +// private Integer corePoolSize; +// +// private Integer maxPoolSize; +// +// private Integer queueCapacity; +// +// private Integer keepAliveSeconds; +//} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/token/TokenVerify.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/token/TokenVerify.java new file mode 100644 index 000000000..003c3b26d --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/token/TokenVerify.java @@ -0,0 +1,31 @@ +package com.youlai.mall.oms.config.token; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author huawei + * @desc Token 幂等性校验接口注解 + * 幂等性方案:注解 + 拦截器 + * 注解:@TokenVerify 注解,该注解有两个属性,generate 和 clean + * generate:属性为true是表示请求该方法会生成一个uuid token,同时放入redis中和用户请求中,用于用户下一次请求校验,默认为false + * clean:如果属性为true表示请求该方法需要校验token唯一性,并且在校验通过后清除redis中的token + * 拦截器:TokenVerifyHandler + * 实现原理:拦截所有的请求,如果该请求被 @TokenVerify 注解标识:首先判断该注解属性 generate 是否为true,然后校验属性 clean 是否为true + * 最后,在 WebMvcConfig 配置中配置拦截器 + * @email huawei_code@163.com + * @date 2021/1/21 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface TokenVerify { + + // 是否生成校验token + boolean generate() default false; + + // 是否校验token + boolean verify() default false; + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/token/TokenVerifyHandler.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/token/TokenVerifyHandler.java new file mode 100644 index 000000000..f9d5c5df5 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/config/token/TokenVerifyHandler.java @@ -0,0 +1,45 @@ +package com.youlai.mall.oms.config.token; + +import com.youlai.mall.oms.service.TokenService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author huawei + * @desc + * @email huawei_code@163.com + * @date 2021/1/21 + */ +@Component +@AllArgsConstructor +@Slf4j +public class TokenVerifyHandler extends HandlerInterceptorAdapter { + + @Autowired + private TokenService tokenService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (!(handler instanceof HandlerMethod)) { + return true; + } + + HandlerMethod method = (HandlerMethod) handler; + TokenVerify tokenVerify = method.getMethodAnnotation(TokenVerify.class); + if (tokenVerify != null) { + log.debug("请求:{} 使用 @TokenVerify 注解,被拦截器拦截", request.getRequestURI()); + // 校验token,判断是否重复提交 + tokenService.checkToken(request); + } + return true; + } + + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/admin/OrderController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/admin/OrderController.java new file mode 100644 index 000000000..d36e2993c --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/admin/OrderController.java @@ -0,0 +1,130 @@ +package com.youlai.mall.oms.controller.admin; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.youlai.common.enums.BusinessTypeEnum; +import com.youlai.common.enums.QueryModeEnum; +import com.youlai.common.redis.component.BusinessNoGenerator; +import com.youlai.common.result.Result; +import com.youlai.common.result.ResultCode; +import com.youlai.mall.oms.bo.OrderBO; +import com.youlai.mall.oms.service.IOmsOrderService; +import com.youlai.mall.oms.pojo.OmsOrder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +@Api(tags = "【系统管理】订单服务") +@RestController("") +@RequestMapping("/api.admin/v1/orders") +@Slf4j +@AllArgsConstructor +public class OrderController { + + private IOmsOrderService iOmsOrderService; + + @ApiOperation(value = "列表分页", httpMethod = "GET") + @ApiImplicitParams({ + @ApiImplicitParam(name = "queryMode", value = "查询模式", paramType = "query", dataType = "QueryModeEnum"), + @ApiImplicitParam(name = "page", value = "页码", paramType = "query", dataType = "Long"), + @ApiImplicitParam(name = "limit", value = "每页数量", paramType = "query", dataType = "Long"), + @ApiImplicitParam(name = "orderSn", value = "订单编号", paramType = "query", dataType = "String"), + @ApiImplicitParam(name = "status", value = "订单状态", paramType = "query", dataType = "Integer"), + @ApiImplicitParam(name = "startDate", value = "开始日期", paramType = "query", dataType = "String"), + @ApiImplicitParam(name = "endDate", value = "结束日期", paramType = "query", dataType = "String"), + }) + @GetMapping + public Result list( + String queryMode, + Integer page, + Integer limit, + String orderSn, + Integer status, + String startDate, + String endDate + ) { + QueryModeEnum queryModeEnum = QueryModeEnum.getValue(queryMode); + switch (queryModeEnum) { + case PAGE: + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .like(StrUtil.isNotBlank(orderSn), OmsOrder::getOrderSn, orderSn) + .eq(status != null, OmsOrder::getStatus, status) + .apply(StrUtil.isNotBlank(startDate), + "date_format (gmt_crate,'%Y-%m-%d') >= date_format('" + startDate + "','%Y-%m-%d')") + .apply(StrUtil.isNotBlank(endDate), + "date_format (gmt_crate,'%Y-%m-%d') <= date_format('" + endDate + "','%Y-%m-%d')") + .orderByDesc(OmsOrder::getGmtModified) + .orderByDesc(OmsOrder::getGmtCreate); + + Page result = iOmsOrderService.page(new Page<>(page, limit), queryWrapper); + + return Result.success(result.getRecords(), result.getTotal()); + default: + return Result.failed(ResultCode.QUERY_MODE_IS_NULL); + } + } + + @ApiOperation(value = "订单详情", httpMethod = "GET") + @ApiImplicitParam(name = "id", value = "订单id", required = true, paramType = "path", dataType = "Long") + @GetMapping("/{id}") + public Result detail(@PathVariable Long id) { + OrderBO order = iOmsOrderService.getByOrderId(id); + return Result.success(order); + } + + @ApiOperation(value = "订单提交", httpMethod = "POST") + @ApiImplicitParam(name = "orderBO", value = "实体JSON对象", required = true, paramType = "body", dataType = "OrderBO") + @PostMapping + public Result add(@RequestBody OrderBO orderBO) { + boolean status = iOmsOrderService.save(orderBO); + return Result.judge(status); + } + + @ApiOperation(value = "修改订单", httpMethod = "PUT") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "订单id", required = true, paramType = "path", dataType = "Long"), + @ApiImplicitParam(name = "order", value = "实体JSON对象", required = true, paramType = "body", dataType = "OmsOrder") + }) + @PutMapping(value = "/{id}") + public Result update( + @PathVariable Long id, + @RequestBody OmsOrder order) { + boolean status = iOmsOrderService.updateById(order); + return Result.judge(status); + } + + + @ApiOperation(value = "订单提交", httpMethod = "POST") + @PostMapping("/submit") + public Result submit(Boolean openTransaction) { + boolean status; + if (openTransaction) { + status = iOmsOrderService.submitWithGlobalTransactional(); + } else { + status = iOmsOrderService.submit(); + } + return Result.judge(status); + } + + @ApiOperation(value = "订单详情", httpMethod = "GET") + @ApiImplicitParam(name = "id", value = "订单id", required = true, paramType = "path", dataType = "Long") + @GetMapping("/{id}/detail") + public Result orderDetail(@PathVariable Long id) { + OmsOrder order = iOmsOrderService.getById(id); + return Result.success(order); + } + + private BusinessNoGenerator businessNoGenerator; + + @PostMapping("/order_sn") + public Result generateOrderSn() { + String orderSn = businessNoGenerator.generate(BusinessTypeEnum.ORDER); + log.info("订单编号:{}", orderSn); + return Result.success(orderSn); + } +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java new file mode 100644 index 000000000..3eb55e4c6 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java @@ -0,0 +1,90 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.mall.oms.bo.CartItemBo; +import com.youlai.mall.oms.bo.CartItemCheckBo; +import com.youlai.mall.oms.pojo.vo.CartVo; +import com.youlai.mall.oms.service.CartService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.concurrent.ExecutionException; + +/** + * 购物车 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ + +@Api(tags = "购物车接口") +@RestController +@RequestMapping("/api.app/v1/carts") +@Slf4j +@AllArgsConstructor +public class CartController { + + private CartService cartService; + + @ApiOperation(value = "查询购物车", httpMethod = "GET") + @GetMapping + public Result detail() { + CartVo cart = cartService.detail(); + return Result.success(cart); + } + + @ApiOperation(value = "添加购物车", httpMethod = "POST") + @ApiImplicitParam(name = "skuId", value = "商品SKU Id", required = true, paramType = "param", dataType = "String") + @PostMapping + public Result save(@RequestParam("skuId") String skuId) throws ExecutionException, InterruptedException { + cartService.save(skuId); + return Result.success(); + } + + @ApiOperation(value = "修改购物车商品数量", httpMethod = "PUT") + @ApiImplicitParam(name = "cartItemBo", value = "实体JSON对象", required = true, paramType = "body", dataType = "CartItemBo") + @PutMapping + public Result update(@Validated @RequestBody CartItemBo cartItemBo) { + cartService.update(cartItemBo); + return Result.success(); + } + + @ApiOperation(value = "是否选择购物车中商品", httpMethod = "PUT") + @ApiImplicitParam(name = "cartItemChooseBo", value = "实体JSON对象", required = true, paramType = "body", dataType = "CartItemChooseBo") + @PutMapping("/check") + public Result check(@Validated @RequestBody CartItemCheckBo cartItemCheckBo) { + cartService.check(cartItemCheckBo); + return Result.success(); + } + + @ApiOperation(value = "全选/全不选择购物车", httpMethod = "PUT") + @ApiImplicitParam(name = "check", value = "全选/全不选", required = true, paramType = "param", dataType = "Long") + @PutMapping("/checkAll") + public Result checkAll(@RequestParam("check") Integer check) { + cartService.checkAll(check); + return Result.success(); + } + + @ApiOperation(value = "批量删除购物车", httpMethod = "DELETE") + @ApiImplicitParam(name = "skuIds", value = "商品sku id集合", required = true, paramType = "param", dataType = "List") + @DeleteMapping + public Result delete(@RequestParam("skuIds") List skuIds) { + cartService.deleteBatch(skuIds); + return Result.success(); + } + + @ApiOperation(value = "清空购物车", httpMethod = "GET") + @GetMapping("/clear") + public Result clear() { + cartService.clear(); + return Result.success(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java new file mode 100644 index 000000000..8a89539ba --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java @@ -0,0 +1,138 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.mall.oms.pojo.entity.OrderEntity; +import com.youlai.mall.oms.pojo.vo.OrderConfirmVO; +import com.youlai.mall.oms.pojo.vo.OrderListVO; +import com.youlai.mall.oms.pojo.vo.OrderSubmitResultVO; +import com.youlai.mall.oms.pojo.vo.OrderSubmitVO; +import com.youlai.mall.oms.service.OrderService; +import io.seata.spring.annotation.GlobalTransactional; +import io.swagger.annotations.*; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.util.List; +import java.util.concurrent.ExecutionException; + + +/** + * 订单详情表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Api(tags = "APP订单详情接口") +@RestController +@RequestMapping("/api.app/v1/orders") +@Slf4j +@AllArgsConstructor +public class OrderController { + + private OrderService orderService; + + /** + * 订单确认信息,生成订单 + * 如果入参传了skuId,则以当前skuId为准,商品数量默认为1 + * 如果没有传,则从购物车中获取数据 + * 如果购物车中没有数据,则返回为空 + * + * @return + */ + @ApiOperation(value = "订单确认信息", httpMethod = "POST") + @ApiImplicitParams({ + @ApiImplicitParam(name = "skuId", value = "商品ID", required = true, paramType = "param", dataType = "String"), + @ApiImplicitParam(name = "number", value = "商品数量", required = true, defaultValue = "1", paramType = "param", dataType = "Integer") + + }) + @PostMapping("/confirm") + public Result confirm(@RequestParam(value = "skuId", required = false) String skuId, + @RequestParam(value = "number", defaultValue = "1") Integer number) { + return Result.success(orderService.confirm(skuId, number)); + } + + @ApiOperation(value = "提交订单", httpMethod = "POST") + @ApiImplicitParam(name = "submit", value = "提交订单参数", required = true, paramType = "body", dataType = "OrderSubmitVO") + @PostMapping("/submit") + public Result submit(@Valid @RequestBody OrderSubmitVO submit) throws ExecutionException, InterruptedException { + log.info("提交订单:{}", submit); + return Result.success(orderService.submit(submit)); + } + + + /** + * 根据订单状态查询订单列表 + * 步骤: + * 1、入参 status 表示订单状态 + * 2、status = 0 表示查询所有订单 + * 3、已删除订单无法查询 + */ + @ApiOperation("订单列表查询") + @GetMapping("/list") + public Result> list(@ApiParam(name = "status",value = "订单状态",required = true,defaultValue = "0") + @RequestParam(value = "status",required = true,defaultValue = "0") Integer status) { + List orderList = orderService.list(status); + + return Result.success(orderList); + } + + + /** + * 信息 + */ + @RequestMapping("/info/{id}") + @GlobalTransactional + //@RequiresPermissions("oms:order:info") + public Result info(@PathVariable("id") Long id) { + OrderEntity order = orderService.getById(id); + + return Result.success(order); + } + + /** + * 保存 + */ + @RequestMapping("/save") + //@RequiresPermissions("oms:order:save") + public Result save(@RequestBody OrderEntity order) { + orderService.save(order); + + return Result.success(); + } + + /** + * 修改 + */ + @RequestMapping("/update") + //@RequiresPermissions("oms:order:update") + public Result update(@RequestBody OrderEntity order) { + orderService.updateById(order); + + return Result.success(); + } + + /** + * 取消订单 + */ + @PutMapping("/cancel") + @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "param", dataType = "String") + public Result cancelOrder(@RequestParam("id") String id) { + orderService.cancelOrder(id); + return Result.success(); + } + + /** + * 删除 + */ + @DeleteMapping + @ApiImplicitParam(name = "id", value = "订单ID", required = true, paramType = "param", dataType = "String") + public Result delete(@RequestParam("id") String id) { + orderService.deleteOrder(id); + return Result.success(); + } + + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderDeliveryController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderDeliveryController.java new file mode 100644 index 000000000..d72ae8e20 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderDeliveryController.java @@ -0,0 +1,84 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderDeliveryEntity; +import com.youlai.mall.oms.service.OrderDeliveryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; + + + +/** + * 订单物流记录表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@RestController +@RequestMapping("oms/orderdelivery") +public class OrderDeliveryController { + @Autowired + private OrderDeliveryService orderDeliveryService; + + /** + * 列表 + */ + @RequestMapping("/list") + //@RequiresPermissions("oms:orderdelivery:list") + public Result list(@RequestParam Map params){ + PageUtils page = orderDeliveryService.queryPage(params); + + return Result.success(page); + } + + + /** + * 信息 + */ + @RequestMapping("/info/{id}") + //@RequiresPermissions("oms:orderdelivery:info") + public Result info(@PathVariable("id") Long id){ + OrderDeliveryEntity orderDelivery = orderDeliveryService.getById(id); + + return Result.success(orderDelivery); + } + + /** + * 保存 + */ + @RequestMapping("/save") + //@RequiresPermissions("oms:orderdelivery:save") + public Result save(@RequestBody OrderDeliveryEntity orderDelivery){ + orderDeliveryService.save(orderDelivery); + + return Result.success(); + } + + /** + * 修改 + */ + @RequestMapping("/update") + //@RequiresPermissions("oms:orderdelivery:update") + public Result update(@RequestBody OrderDeliveryEntity orderDelivery){ + orderDeliveryService.updateById(orderDelivery); + + return Result.success(); + } + + /** + * 删除 + */ + @RequestMapping("/delete") + //@RequiresPermissions("oms:orderdelivery:delete") + public Result delete(@RequestBody Long[] ids){ + orderDeliveryService.removeByIds(Arrays.asList(ids)); + + return Result.success(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderGoodsController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderGoodsController.java new file mode 100644 index 000000000..416c6cc5f --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderGoodsController.java @@ -0,0 +1,84 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderGoodsEntity; +import com.youlai.mall.oms.service.OrderGoodsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; + + + +/** + * 订单商品信息表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@RestController +@RequestMapping("oms/ordergoods") +public class OrderGoodsController { + @Autowired + private OrderGoodsService orderGoodsService; + + /** + * 列表 + */ + @RequestMapping("/list") + //@RequiresPermissions("oms:ordergoods:list") + public Result list(@RequestParam Map params){ + PageUtils page = orderGoodsService.queryPage(params); + + return Result.success(page); + } + + + /** + * 信息 + */ + @RequestMapping("/info/{id}") + //@RequiresPermissions("oms:ordergoods:info") + public Result info(@PathVariable("id") Long id){ + OrderGoodsEntity orderGoods = orderGoodsService.getById(id); + + return Result.success(orderGoods); + } + + /** + * 保存 + */ + @RequestMapping("/save") + //@RequiresPermissions("oms:ordergoods:save") + public Result save(@RequestBody OrderGoodsEntity orderGoods){ + orderGoodsService.save(orderGoods); + + return Result.success(); + } + + /** + * 修改 + */ + @RequestMapping("/update") + //@RequiresPermissions("oms:ordergoods:update") + public Result update(@RequestBody OrderGoodsEntity orderGoods){ + orderGoodsService.updateById(orderGoods); + + return Result.success(); + } + + /** + * 删除 + */ + @RequestMapping("/delete") + //@RequiresPermissions("oms:ordergoods:delete") + public Result delete(@RequestBody Long[] ids){ + orderGoodsService.removeByIds(Arrays.asList(ids)); + + return Result.success(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderLogsController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderLogsController.java new file mode 100644 index 000000000..c69b88576 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderLogsController.java @@ -0,0 +1,84 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderLogsEntity; +import com.youlai.mall.oms.service.OrderLogsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; + + + +/** + * 订单操作历史记录 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@RestController +@RequestMapping("oms/order/logs") +public class OrderLogsController { + @Autowired + private OrderLogsService orderLogsService; + + /** + * 列表 + */ + @RequestMapping("/list") + //@RequiresPermissions("oms:orderlogs:list") + public Result list(@RequestParam Map params){ + PageUtils page = orderLogsService.queryPage(params); + + return Result.success(page); + } + + + /** + * 信息 + */ + @RequestMapping("/info/{id}") + //@RequiresPermissions("oms:orderlogs:info") + public Result info(@PathVariable("id") Long id){ + OrderLogsEntity orderLogs = orderLogsService.getById(id); + + return Result.success(orderLogs); + } + + /** + * 保存 + */ + @RequestMapping("/save") + //@RequiresPermissions("oms:orderlogs:save") + public Result save(@RequestBody OrderLogsEntity orderLogs){ + orderLogsService.save(orderLogs); + + return Result.success(); + } + + /** + * 修改 + */ + @RequestMapping("/update") + //@RequiresPermissions("oms:orderlogs:update") + public Result update(@RequestBody OrderLogsEntity orderLogs){ + orderLogsService.updateById(orderLogs); + + return Result.success(); + } + + /** + * 删除 + */ + @RequestMapping("/delete") + //@RequiresPermissions("oms:orderlogs:delete") + public Result delete(@RequestBody Long[] ids){ + orderLogsService.removeByIds(Arrays.asList(ids)); + + return Result.success(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderPayController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderPayController.java new file mode 100644 index 000000000..ddbbfbd21 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderPayController.java @@ -0,0 +1,122 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.common.result.Result; +import com.youlai.common.utils.EnumUtils; +import com.youlai.mall.oms.enums.OrderPayTypeEnum; +import com.youlai.mall.oms.pojo.entity.OrderPayEntity; +import com.youlai.mall.oms.pojo.form.OrderPayForm; +import com.youlai.mall.oms.pojo.vo.PayInfoVO; +import com.youlai.mall.oms.service.OrderPayService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; + + +/** + * 订单支付服务 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Api(tags = "订单支付服务") +@RestController +@RequestMapping("/api.app/v1/order/pay") +@Slf4j +public class OrderPayController { + @Autowired + private OrderPayService orderPayService; + + /** + * 订单支付 + * 1、根据支付类型选择正确支付方式(1:微信支付;2:支付宝支付;3:余额支付) + * 2、根据订单id查询订单价格,进行支付(在整个支付的过程中进行事务控制,保证整个操作的原子性) + * 3、将支付结果记录日志并返回给前端 + * + * @param orderPayForm 订单支付表单 + * @return + */ + @ApiOperation("订单支付") + @PostMapping + public Result doPay(@Validated @RequestBody OrderPayForm orderPayForm) { + OrderPayTypeEnum payTypeEnum = EnumUtils.getByCode(orderPayForm.getPayType(), OrderPayTypeEnum.class); + if (payTypeEnum == null) { + return Result.failed("请选择正确的支付方式"); + } + log.info("订单支付,orderId={},支付方式={}", orderPayForm.getOrderId(), payTypeEnum.desc); + if (payTypeEnum == OrderPayTypeEnum.BALANCE) { + orderPayService.balancePay(orderPayForm.getOrderId()); + } + return Result.success(); + } + + @ApiOperation(value = "获取订单支付详情") + @GetMapping("/info") + public Result info(@ApiParam(name = "orderId", value = "订单ID", required = true, defaultValue = "1") @RequestParam("orderId") String orderId) { + return Result.success(orderPayService.info(orderId)); + } + + /** + * 列表 + */ + @RequestMapping("/list") + public Result list(@RequestParam Map params) { + PageUtils page = orderPayService.queryPage(params); + + return Result.success(page); + } + + + /** + * 信息 + */ + @RequestMapping("/info/{id}") + //@RequiresPermissions("oms:orderpay:info") + public Result info(@PathVariable("id") Long id) { + OrderPayEntity orderPay = orderPayService.getById(id); + + return Result.success(orderPay); + } + + /** + * 保存 + */ + @RequestMapping("/save") + //@RequiresPermissions("oms:orderpay:save") + public Result save(@RequestBody OrderPayEntity orderPay) { + orderPayService.save(orderPay); + + return Result.success(); + } + + /** + * 修改 + */ + @RequestMapping("/update") + //@RequiresPermissions("oms:orderpay:update") + public Result update(@RequestBody OrderPayEntity orderPay) { + orderPayService.updateById(orderPay); + + return Result.success(); + } + + /** + * 删除 + */ + @RequestMapping("/delete") + //@RequiresPermissions("oms:orderpay:delete") + public Result delete(@RequestBody Long[] ids) { + orderPayService.removeByIds(Arrays.asList(ids)); + + return Result.success(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderSettingController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderSettingController.java new file mode 100644 index 000000000..24170306c --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderSettingController.java @@ -0,0 +1,84 @@ +package com.youlai.mall.oms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderSettingEntity; +import com.youlai.mall.oms.service.OrderSettingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.Map; + + + +/** + * 订单配置信息 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@RestController +@RequestMapping("oms/ordersetting") +public class OrderSettingController { + @Autowired + private OrderSettingService orderSettingService; + + /** + * 列表 + */ + @RequestMapping("/list") + //@RequiresPermissions("oms:ordersetting:list") + public Result list(@RequestParam Map params){ + PageUtils page = orderSettingService.queryPage(params); + + return Result.success(page); + } + + + /** + * 信息 + */ + @RequestMapping("/info/{id}") + //@RequiresPermissions("oms:ordersetting:info") + public Result info(@PathVariable("id") Long id){ + OrderSettingEntity orderSetting = orderSettingService.getById(id); + + return Result.success(orderSetting); + } + + /** + * 保存 + */ + @RequestMapping("/save") + //@RequiresPermissions("oms:ordersetting:save") + public Result save(@RequestBody OrderSettingEntity orderSetting){ + orderSettingService.save(orderSetting); + + return Result.success(); + } + + /** + * 修改 + */ + @RequestMapping("/update") + //@RequiresPermissions("oms:ordersetting:update") + public Result update(@RequestBody OrderSettingEntity orderSetting){ + orderSettingService.updateById(orderSetting); + + return Result.success(); + } + + /** + * 删除 + */ + @RequestMapping("/delete") + //@RequiresPermissions("oms:ordersetting:delete") + public Result delete(@RequestBody Long[] ids){ + orderSettingService.removeByIds(Arrays.asList(ids)); + + return Result.success(); + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderDao.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderDao.java new file mode 100644 index 000000000..bcb1583ea --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderDao.java @@ -0,0 +1,17 @@ +package com.youlai.mall.oms.dao; + +import com.youlai.mall.oms.pojo.entity.OrderEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 订单详情表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Mapper +public interface OrderDao extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderDeliveryDao.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderDeliveryDao.java new file mode 100644 index 000000000..d17ff53de --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderDeliveryDao.java @@ -0,0 +1,17 @@ +package com.youlai.mall.oms.dao; + +import com.youlai.mall.oms.pojo.entity.OrderDeliveryEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 订单物流记录表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Mapper +public interface OrderDeliveryDao extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderGoodsDao.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderGoodsDao.java new file mode 100644 index 000000000..a0013bfa5 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderGoodsDao.java @@ -0,0 +1,17 @@ +package com.youlai.mall.oms.dao; + +import com.youlai.mall.oms.pojo.entity.OrderGoodsEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 订单商品信息表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Mapper +public interface OrderGoodsDao extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderLogsDao.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderLogsDao.java new file mode 100644 index 000000000..ed1667b09 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderLogsDao.java @@ -0,0 +1,17 @@ +package com.youlai.mall.oms.dao; + +import com.youlai.mall.oms.pojo.entity.OrderLogsEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 订单操作历史记录 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Mapper +public interface OrderLogsDao extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderPayDao.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderPayDao.java new file mode 100644 index 000000000..40d78bcf8 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderPayDao.java @@ -0,0 +1,17 @@ +package com.youlai.mall.oms.dao; + +import com.youlai.mall.oms.pojo.entity.OrderPayEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 支付信息表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Mapper +public interface OrderPayDao extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderSettingDao.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderSettingDao.java new file mode 100644 index 000000000..86acd89fc --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/dao/OrderSettingDao.java @@ -0,0 +1,17 @@ +package com.youlai.mall.oms.dao; + +import com.youlai.mall.oms.pojo.entity.OrderSettingEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * 订单配置信息 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +@Mapper +public interface OrderSettingDao extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/mapper/OmsOrderItemMapper.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/mapper/OmsOrderItemMapper.java new file mode 100644 index 000000000..9ac06dca1 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/mapper/OmsOrderItemMapper.java @@ -0,0 +1,10 @@ +package com.youlai.mall.oms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.mall.oms.pojo.OmsOrderItem; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface OmsOrderItemMapper extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/mapper/OmsOrderMapper.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/mapper/OmsOrderMapper.java new file mode 100644 index 000000000..6696b2a1c --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/mapper/OmsOrderMapper.java @@ -0,0 +1,10 @@ +package com.youlai.mall.oms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.youlai.mall.oms.pojo.OmsOrder; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface OmsOrderMapper extends BaseMapper { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/CartService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/CartService.java new file mode 100644 index 000000000..f34348bb8 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/CartService.java @@ -0,0 +1,68 @@ +package com.youlai.mall.oms.service; + +import com.youlai.mall.oms.bo.CartItemBo; +import com.youlai.mall.oms.bo.CartItemCheckBo; +import com.youlai.mall.oms.pojo.vo.CartVo; + +import java.util.List; +import java.util.concurrent.ExecutionException; + +/** + * 购物车业务接口 + */ +public interface CartService { + + /** + * 添加商品到购物车 + * @param skuId 商品模型 + */ + void save(String skuId) throws ExecutionException, InterruptedException; + + /** + * 修改购物车商品数量 + * @param cartItemBo + */ + void update(CartItemBo cartItemBo); + + /** + * 修改购物车中商品是否选中状态 + * @param cartItemCheckBo + */ + void check(CartItemCheckBo cartItemCheckBo); + + /** + * 全选/全不选购物车 + * @param check + */ + void checkAll(Integer check); + + /** + * 删除购物车中的商品 + * @param skuId 商品id + */ + void delete(Long skuId); + + /** + * 批量删除购物车中的商品 + * @param skuIds 商品id集合 + */ + void deleteBatch(List skuIds); + + /** + * 查询购物车详情 + * @return + */ + CartVo detail(); + + /** + * 清空购物车 + */ + void clear(); + + /** + * 清空购物车中已选择商品 + */ + void cleanSelected(); + + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/IOmsOrderItemService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/IOmsOrderItemService.java new file mode 100644 index 000000000..e23a355d1 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/IOmsOrderItemService.java @@ -0,0 +1,8 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.mall.oms.pojo.OmsOrderItem; + +public interface IOmsOrderItemService extends IService { + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/IOmsOrderService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/IOmsOrderService.java new file mode 100644 index 000000000..b3bc89fbe --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/IOmsOrderService.java @@ -0,0 +1,16 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.mall.oms.bo.OrderBO; +import com.youlai.mall.oms.pojo.OmsOrder; + +public interface IOmsOrderService extends IService { + + boolean save(OrderBO orderBO); + + OrderBO getByOrderId(Long id); + + boolean submit(); + + boolean submitWithGlobalTransactional(); +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderDeliveryService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderDeliveryService.java new file mode 100644 index 000000000..af7262ec9 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderDeliveryService.java @@ -0,0 +1,20 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderDeliveryEntity; + +import java.util.Map; + +/** + * 订单物流记录表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +public interface OrderDeliveryService extends IService { + + PageUtils queryPage(Map params); +} + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderGoodsService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderGoodsService.java new file mode 100644 index 000000000..f59d8d7c6 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderGoodsService.java @@ -0,0 +1,26 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderGoodsEntity; + +import java.util.List; +import java.util.Map; + +/** + * 订单商品信息表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +public interface OrderGoodsService extends IService { + + PageUtils queryPage(Map params); + + List getByOrderId(Long orderId); + + Map> getByOrderIds(List orderIds); + +} + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderLogsService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderLogsService.java new file mode 100644 index 000000000..9c41523d1 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderLogsService.java @@ -0,0 +1,37 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderLogsEntity; + +import java.util.Map; + +/** + * 订单操作历史记录 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +public interface OrderLogsService extends IService { + + PageUtils queryPage(Map params); + + /** + * 添加订单操作日志记录 + * @param orderId 订单id + * @param orderStatus 订单状态 + * @param user 操作人员 + * @param detail 描述信息 + */ + void addOrderLogs(Long orderId, Integer orderStatus, String user, String detail); + + /** + * 添加订单操作日志记录 + * @param orderId 订单id + * @param orderStatus 订单状态 + * @param detail 描述 + */ + void addOrderLogs(Long orderId, Integer orderStatus, String detail); +} + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderPayService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderPayService.java new file mode 100644 index 000000000..ed4e0d32d --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderPayService.java @@ -0,0 +1,34 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderPayEntity; +import com.youlai.mall.oms.pojo.vo.PayInfoVO; + +import java.util.Map; + +/** + * 支付信息表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +public interface OrderPayService extends IService { + + PageUtils queryPage(Map params); + + /** + * 获取订单支付详情 + * @param orderId 订单id + * @return + */ + PayInfoVO info(String orderId); + + /** + * 订单支付 + * @param orderId 订单ID + */ + void balancePay(String orderId); +} + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderRabbitService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderRabbitService.java new file mode 100644 index 000000000..8e179aab5 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderRabbitService.java @@ -0,0 +1,22 @@ +package com.youlai.mall.oms.service; + +import com.rabbitmq.client.Channel; +import org.springframework.amqp.core.Message; + +/** + * @author huawei + * @desc Order RabbitMQ 业务类 + * @email huawei_code@163.com + * @date 2021/2/4 + */ +public interface OrderRabbitService { + + /** + * 订单超时释放 + * + * @param orderSn + * @param message + * @param channel + */ + void releaseOrder(String orderSn, Message message, Channel channel); +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderService.java new file mode 100644 index 000000000..5d52a0499 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderService.java @@ -0,0 +1,89 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderEntity; +import com.youlai.mall.oms.pojo.vo.OrderConfirmVO; +import com.youlai.mall.oms.pojo.vo.OrderListVO; +import com.youlai.mall.oms.pojo.vo.OrderSubmitResultVO; +import com.youlai.mall.oms.pojo.vo.OrderSubmitVO; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +/** + * 订单详情表 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +public interface OrderService extends IService { + + PageUtils queryPage(Map params); + + /** + * 订单确认页信息 + * + * @param skuId 商品id,非必填参数 + * @param number 商品数量 + * @return + */ + OrderConfirmVO confirm(String skuId, Integer number); + + /** + * 提交订单 + * + * @param submit 订单提交参数 + */ + OrderSubmitResultVO submit(OrderSubmitVO submit) throws ExecutionException, InterruptedException; + + /** + * 根据订单号查询订单详情 + * + * @param orderSn 订单号 + * @return + */ + OrderEntity getByOrderSn(String orderSn); + + /** + * 系统关闭订单 + * + * @param orderSn 订单号 + */ + boolean closeOrderBySystem(String orderSn); + + /** + * 取消订单接口 + * + * @param id 订单id + * @return 是否取消成功 + */ + boolean cancelOrder(String id); + + /** + * 删除订单 + * + * @param id 订单id + * @return 是否删除成功 + */ + boolean deleteOrder(String id); + + /** + * 订单列表查询 + * + * @param status 订单状态 + * @return 订单列表 + */ + List list(Integer status); + + /** + * 根据订单id获取订单信息 + * + * @param id 订单id + * @return 订单信息 + */ + OrderEntity getByOrderId(String id); +} + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderSettingService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderSettingService.java new file mode 100644 index 000000000..456862b4a --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/OrderSettingService.java @@ -0,0 +1,20 @@ +package com.youlai.mall.oms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.pojo.entity.OrderSettingEntity; + +import java.util.Map; + +/** + * 订单配置信息 + * + * @author huawei + * @email huawei_code@163.com + * @date 2020-12-30 22:31:10 + */ +public interface OrderSettingService extends IService { + + PageUtils queryPage(Map params); +} + diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/TokenService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/TokenService.java new file mode 100644 index 000000000..e0e140dd5 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/TokenService.java @@ -0,0 +1,25 @@ +package com.youlai.mall.oms.service; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author huawei + * @desc + * @email huawei_code@163.com + * @date 2021/1/21 + */ +public interface TokenService { + + /** + * 为当前用户请求生成Token + * + * @return token + */ + String generateToken(); + + /** + * 校验 Token 是否正确 + * @param request 当前请求 + */ + void checkToken(HttpServletRequest request); +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java new file mode 100644 index 000000000..295dd10de --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java @@ -0,0 +1,175 @@ +package com.youlai.mall.oms.service.impl; + +import com.youlai.common.result.Result; +import com.youlai.common.web.util.RequestUtils; +import com.youlai.mall.pms.api.ProductFeignService; +import com.youlai.mall.oms.bo.CartItemBo; +import com.youlai.mall.oms.bo.CartItemCheckBo; +import com.youlai.mall.pms.pojo.dto.SkuDTO; +import com.youlai.mall.oms.pojo.vo.CartItemVo; +import com.youlai.mall.oms.pojo.vo.CartVo; +import com.youlai.mall.oms.service.CartService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.BoundHashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static com.youlai.common.redis.constant.RedisKeyConstants.MALL_CART_KEY; + +/** + * 购物车模块搭建步骤 + * 1、用户登录后才能操作购物车 + * *********添加购物车************* + * 1、获取当前登录用户 + * 2、添加商品到购物车 + * 2.1、如果购物车中已经有该商品的相关数据 + * 2.1.1、修改购物车商品数量 + * 2.2、如果购物车中没有该商品,新增该商品 + * 2.2.1、调用商品服务查询商品sku详情 + * 2.2.2、封装CartItem实体类 + * *********修改购物车************* + * *********删除购物车************* + * *********查询购物车************* + */ + +@Service +@Slf4j +@AllArgsConstructor +public class CartServiceImpl implements CartService { + + private RedisTemplate redisTemplate; + + private ProductFeignService productFeignService; + + + @Override + public void save(String skuId) throws ExecutionException, InterruptedException { + log.info("添加商品到购物车,form:{}", skuId); + BoundHashOperations cartOps = getCartOps(); + if (cartOps.get(skuId) != null) { + CartItemVo cartItem = (CartItemVo) cartOps.get(skuId); + Integer number = cartItem.getNumber() + 1; + cartItem.setNumber(number); + cartOps.put(skuId, cartItem); + return; + } + + CartItemVo cartItem = new CartItemVo(); + // 添加新商品到购物车 + CompletableFuture skuInfoFuture = CompletableFuture.runAsync(() -> { + //1、远程查询商品详情 + Result skuInfo = productFeignService.getSkuById(Long.parseLong(skuId)); + SkuDTO data = skuInfo.getData(); + cartItem.setSkuId(Long.parseLong(skuId)); + cartItem.setChecked(true); + cartItem.setSkuName(data.getName()); + cartItem.setSkuImg(data.getPicUrl()); + cartItem.setNumber(1); + cartItem.setPrice(data.getPrice()); + cartItem.setStock(data.getStock()); + + }); + //2、远程查询商品属性 + //3、远程查询库存 + CompletableFuture allOf = CompletableFuture.allOf(skuInfoFuture); + allOf.get(); + cartOps.put(skuId, cartItem); + + + } + + @Override + public void update(CartItemBo cartItemBo) { + log.info("修改购物车商品数量,form:{}", cartItemBo); + BoundHashOperations cartOps = getCartOps(); + CartItemVo cartItem = (CartItemVo) cartOps.get(cartItemBo.getSkuId().toString()); + if (cartItem == null) { + return; + } + cartItem.setNumber(cartItemBo.getNumber()); + cartOps.put(cartItemBo.getSkuId().toString(), cartItem); + } + + @Override + public void check(CartItemCheckBo cartItemCheckBo) { + log.info("修改购物车商品选中状态,form:{}", cartItemCheckBo); + BoundHashOperations cartOps = getCartOps(); + CartItemVo cartItem = (CartItemVo) cartOps.get(cartItemCheckBo.getSkuId().toString()); + if (cartItem == null) { + return; + } + cartItem.setChecked(cartItemCheckBo.getCheck() == 1); + cartOps.put(cartItemCheckBo.getSkuId().toString(), cartItem); + } + + @Override + public void checkAll(Integer check) { + log.info("全选/全不选购物车商品状态,check:{}", check); + BoundHashOperations cartOps = getCartOps(); + for (Object value : cartOps.values()) { + CartItemVo cartItem = (CartItemVo) value; + cartItem.setChecked(check == 1); + cartOps.put(cartItem.getSkuId().toString(), cartItem); + } + } + + @Override + public void delete(Long skuId) { + log.info("删除购物车,商品id:{}", skuId); + BoundHashOperations cartOps = getCartOps(); + cartOps.delete(skuId); + } + + @Override + public void deleteBatch(List skuIds) { + log.info("批量删除购物车,商品id集合:{}", skuIds); + BoundHashOperations cartOps = getCartOps(); + for (String skuId : skuIds) { + cartOps.delete(skuId); + } + } + + @Override + public CartVo detail() { + log.info("查询购物车详情"); + BoundHashOperations cartOps = getCartOps(); + List items = cartOps.values(); + CartVo cartVo = new CartVo(); + cartVo.setItems(items); + return cartVo; + } + + @Override + public void clear() { + log.info("清空购物车"); + Long userId = RequestUtils.getUserId(); + String cartKey = MALL_CART_KEY + userId; + redisTemplate.delete(cartKey); + + } + + @Override + public void cleanSelected() { + log.info("清空购物车中已选择商品"); + BoundHashOperations cartOps = getCartOps(); + for (Object value : cartOps.values()) { + CartItemVo cartItem = (CartItemVo) value; + if (cartItem.isChecked()) { + log.info("清空购物车中商品,商品id:{} | 名称:{}", cartItem.getSkuId(), cartItem.getSkuName()); + cartOps.delete(cartItem.getSkuId().toString()); + } + } + } + + private BoundHashOperations getCartOps() { + Long userId = RequestUtils.getUserId(); + String cartKey = MALL_CART_KEY + userId; + BoundHashOperations operations = redisTemplate.boundHashOps(cartKey); + return operations; + } +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OmsOrderItemServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OmsOrderItemServiceImpl.java new file mode 100644 index 000000000..fb1d9c2d1 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OmsOrderItemServiceImpl.java @@ -0,0 +1,11 @@ +package com.youlai.mall.oms.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.mall.oms.mapper.OmsOrderItemMapper; +import com.youlai.mall.oms.pojo.OmsOrderItem; +import com.youlai.mall.oms.service.IOmsOrderItemService; +import org.springframework.stereotype.Service; + +@Service +public class OmsOrderItemServiceImpl extends ServiceImpl implements IOmsOrderItemService { +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OmsOrderServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OmsOrderServiceImpl.java new file mode 100644 index 000000000..0479c1673 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OmsOrderServiceImpl.java @@ -0,0 +1,119 @@ +package com.youlai.mall.oms.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.result.Result; +import com.youlai.common.web.exception.BizException; +import com.youlai.mall.oms.bo.OrderBO; +import com.youlai.mall.oms.mapper.OmsOrderMapper; +import com.youlai.mall.oms.pojo.OmsOrder; +import com.youlai.mall.oms.pojo.OmsOrderItem; +import com.youlai.mall.oms.service.IOmsOrderItemService; +import com.youlai.mall.oms.service.IOmsOrderService; +import com.youlai.mall.pms.api.ProductFeignService; +import com.youlai.mall.ums.api.MemberFeignService; +import com.youlai.mall.ums.pojo.dto.MemberDTO; +import io.seata.spring.annotation.GlobalTransactional; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Service +@AllArgsConstructor +@Slf4j +public class OmsOrderServiceImpl extends ServiceImpl implements IOmsOrderService { + + private IOmsOrderItemService iOmsOrderItemService; + + private MemberFeignService memberFeignService; + + /** + * 提交订单 + * + * @param orderBO + * @return + */ + @Override + public boolean save(OrderBO orderBO) { + // 订单 + OmsOrder order = orderBO.getOrder(); + String orderSn = IdUtil.createSnowflake(1, 1).nextIdStr(); + order.setOrderSn(orderSn); + this.save(order); + + // 订单明细 + List orderItems = orderBO.getOrderItems(); + if (CollectionUtil.isEmpty(orderItems)) { + throw new BizException("订单明细不能为空"); + } + orderItems.forEach(item -> { + item.setOrderId(order.getId()); + }); + iOmsOrderItemService.saveBatch(orderItems); + return true; + } + + @Override + public OrderBO getByOrderId(Long orderId) { + OrderBO orderBO = new OrderBO(); + // 订单 + OmsOrder order = this.getById(orderId); + if (order == null) { + throw new BizException("订单不存在"); + } + // 订单明细 + List orderItems = iOmsOrderItemService.list( + new LambdaQueryWrapper().eq(OmsOrderItem::getOrderId, orderId) + ); + orderItems = Optional.ofNullable(orderItems).orElse(new ArrayList<>()); + + // 会员明细 + Result result = memberFeignService.getUserById(order.getUserId()); + MemberDTO member = result.getData(); + orderBO.setOrder(order).setOrderItems(orderItems).setMember(member); + return orderBO; + } + + private ProductFeignService productFeignService; + + @Override + public boolean submit() { + log.info("扣减库存----begin"); + productFeignService.updateStock(1l, -1); + log.info("扣减库存----end"); + + log.info("增加积分----begin"); + memberFeignService.updatePoint(1l, 10); + log.info("增加积分----end"); + + log.info("修改订单状态----begin"); + boolean result = this.update(new LambdaUpdateWrapper().eq(OmsOrder::getId, 1l).set(OmsOrder::getStatus, 901)); + log.info("修改订单状态----end"); + return result; + } + + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public boolean submitWithGlobalTransactional() { + log.info("扣减库存----begin"); + productFeignService.updateStock(1l, -1); + log.info("扣减库存----end"); + + log.info("增加积分----begin"); + memberFeignService.updatePoint(1l, 10); + log.info("增加积分----end"); + + log.info("修改订单状态----begin"); + boolean result = this.update(new LambdaUpdateWrapper().eq(OmsOrder::getId, 1l).set(OmsOrder::getStatus, 901)); + log.info("修改订单状态----end"); + return result; + } + +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderDeliveryServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderDeliveryServiceImpl.java new file mode 100644 index 000000000..eb51b88c5 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderDeliveryServiceImpl.java @@ -0,0 +1,29 @@ +package com.youlai.mall.oms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.base.Query; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.dao.OrderDeliveryDao; +import com.youlai.mall.oms.pojo.entity.OrderDeliveryEntity; +import com.youlai.mall.oms.service.OrderDeliveryService; +import org.springframework.stereotype.Service; + +import java.util.Map; + + +@Service("orderDeliveryService") +public class OrderDeliveryServiceImpl extends ServiceImpl implements OrderDeliveryService { + + @Override + public PageUtils queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return new PageUtils(page); + } + +} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderGoodsServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderGoodsServiceImpl.java new file mode 100644 index 000000000..ad106a43a --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderGoodsServiceImpl.java @@ -0,0 +1,56 @@ +package com.youlai.mall.oms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.base.Query; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.dao.OrderGoodsDao; +import com.youlai.mall.oms.pojo.entity.OrderGoodsEntity; +import com.youlai.mall.oms.service.OrderGoodsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +@Service("orderGoodsService") +@Slf4j +public class OrderGoodsServiceImpl extends ServiceImpl implements OrderGoodsService { + + @Override + public PageUtils queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return new PageUtils(page); + } + + @Override + public List getByOrderId(Long orderId) { + log.info("根据订单id,查询订单商品列表,orderId={}", orderId); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.ge("order_id", orderId); + return baseMapper.selectList(queryWrapper); + } + + @Override + public Map> getByOrderIds(List orderIds) { + QueryWrapper orderGoodsQuery = new QueryWrapper<>(); + orderGoodsQuery.in("order_id", orderIds).orderByDesc("order_id", "id"); + List orderGoods = this.list(orderGoodsQuery); + if (orderGoods == null || orderGoods.size() == 0) { + log.info("根据订单ID列表查询商品为空,orderIds={}", orderIds); + return new HashMap<>(8); + } + Map> orderGoodsMap = orderGoods.stream() + .collect(Collectors.groupingBy(OrderGoodsEntity::getOrderId)); + return orderGoodsMap; + } + +} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderLogsServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderLogsServiceImpl.java new file mode 100644 index 000000000..4b3546dd4 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderLogsServiceImpl.java @@ -0,0 +1,53 @@ +package com.youlai.mall.oms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.base.Query; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.common.web.util.RequestUtils; +import com.youlai.mall.oms.dao.OrderLogsDao; +import com.youlai.mall.oms.pojo.entity.OrderLogsEntity; +import com.youlai.mall.oms.service.OrderLogsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; + + +@Service("orderLogsService") +@Slf4j +public class OrderLogsServiceImpl extends ServiceImpl implements OrderLogsService { + + @Override + public PageUtils queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return new PageUtils(page); + } + + @Override + public void addOrderLogs(Long orderId, Integer orderStatus, String user, String detail) { + try { + log.info("添加订单操作日志,orderId={},detail={}", orderId, detail); + OrderLogsEntity orderLogs = new OrderLogsEntity(); + orderLogs.setDetail(detail); + orderLogs.setOrderId(orderId); + orderLogs.setOrderStatus(orderStatus); + orderLogs.setUser(user); + baseMapper.insert(orderLogs); + } catch (Exception e) { + log.error("添加订单操作日志失败,orderId={}", orderId, e.getMessage()); + } + } + + @Override + public void addOrderLogs(Long orderId, Integer orderStatus, String detail) { + Long userId = RequestUtils.getUserId(); + addOrderLogs(orderId, orderStatus, userId.toString(), detail); + } + +} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderPayServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderPayServiceImpl.java new file mode 100644 index 000000000..8a47f0f10 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderPayServiceImpl.java @@ -0,0 +1,126 @@ +package com.youlai.mall.oms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.base.Query; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.common.result.Result; +import com.youlai.common.result.ResultCode; +import com.youlai.common.utils.EnumUtils; +import com.youlai.common.web.exception.BizException; +import com.youlai.common.web.util.RequestUtils; +import com.youlai.mall.oms.dao.OrderPayDao; +import com.youlai.mall.oms.enums.OrderPayTypeEnum; +import com.youlai.mall.oms.enums.OrderStatusEnum; +import com.youlai.mall.oms.pojo.entity.OrderEntity; +import com.youlai.mall.oms.pojo.entity.OrderPayEntity; +import com.youlai.mall.oms.pojo.vo.PayInfoVO; +import com.youlai.mall.oms.service.OrderLogsService; +import com.youlai.mall.oms.service.OrderPayService; +import com.youlai.mall.oms.service.OrderService; +import com.youlai.mall.ums.api.MemberFeignService; +import com.youlai.mall.ums.pojo.dto.MemberDTO; +import io.seata.spring.annotation.GlobalTransactional; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.Map; + + +@Slf4j +@AllArgsConstructor +@Service("orderPayService") +public class OrderPayServiceImpl extends ServiceImpl implements OrderPayService { + + private OrderService orderService; + + private OrderLogsService orderLogsService; + + private MemberFeignService memberFeignService; + + @Override + public PageUtils queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return new PageUtils(page); + } + + @Override + public PayInfoVO info(String orderId) { + Long userId = RequestUtils.getUserId(); + PayInfoVO payInfoVO = new PayInfoVO(); + // 1、获取订单应支付金额 + OrderEntity orderEntity = orderService.getByOrderId(orderId); + payInfoVO.setPayPrice(orderEntity.getPayAmount()); + + // 2、获取会员余额 + try { + Result memberInfo = memberFeignService.getUserById(RequestUtils.getUserId()); + if (memberInfo != null && memberInfo.getCode().equals(ResultCode.SUCCESS.getCode())) { + MemberDTO data = memberInfo.getData(); + if (data != null) { + payInfoVO.setBalance(data.getBalance()); + } else { + log.error("获取会员信息失败,userId={}", userId); + } + } + } catch (Exception e) { + log.error("获取会员余额失败,userId={}", userId, e); + } + + return payInfoVO; + } + + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public void balancePay(String orderId) { + // 1、查询订单详情,判断订单状态是否是待支付状态 + log.info("订单进入支付流程,orderId:{}", orderId); + OrderEntity order = orderService.getByOrderId(orderId); + OrderStatusEnum orderStatusEnum = EnumUtils.getByCode(order.getStatus(), OrderStatusEnum.class); + if (orderStatusEnum != OrderStatusEnum.NEED_PAY) { + log.error("订单状态异常无法支付,orderStatus={}", orderStatusEnum.desc); + throw new BizException("订单" + orderStatusEnum.desc); + } + + // 2、查询用户信息,判断用户余额是否足够 + Long userId = RequestUtils.getUserId(); + Result memberInfo = memberFeignService.getUserById(userId); + MemberDTO memberInfoData = memberInfo.getData(); + if (memberInfo == null || !memberInfo.getCode().equals(ResultCode.SUCCESS.getCode()) || memberInfoData == null) { + log.error("会员信息异常,无法支付"); + throw new BizException("会员信息异常,无法支付"); + } + if (memberInfoData.getBalance() < order.getPayAmount()) { + log.error("会员余额不足,无法支付,请先充值"); + throw new BizException("会员余额不足,无法支付,请先充值"); + } + + // 3、更新用户余额 + memberFeignService.updateBalance(userId, order.getPayAmount()); + + // 4、更新订单状态、添加订单支付记录、添加订单操作记录 + order.setStatus(OrderStatusEnum.IS_PAY.code); + order.setPayTime(new Date()); + order.setPayType(OrderPayTypeEnum.BALANCE.code); + orderService.updateById(order); + this.save(createOrderPay(order, OrderPayTypeEnum.BALANCE.code)); + orderLogsService.addOrderLogs(order.getId(), OrderStatusEnum.IS_PAY.code, userId.toString(), "支付订单"); + } + + private OrderPayEntity createOrderPay(OrderEntity order, Integer payType) { + OrderPayEntity payEntity = new OrderPayEntity(); + payEntity.setOrderId(order.getId()); + payEntity.setPayAmount(order.getPayAmount()); + payEntity.setPayTime(new Date()); + payEntity.setPayType(payType); + return payEntity; + } + +} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderRabbitServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderRabbitServiceImpl.java new file mode 100644 index 000000000..905f8c255 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderRabbitServiceImpl.java @@ -0,0 +1,86 @@ +package com.youlai.mall.oms.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.rabbitmq.client.Channel; +import com.youlai.common.result.Result; +import com.youlai.common.result.ResultCode; +import com.youlai.common.web.exception.BizException; +import com.youlai.mall.oms.config.rabbitmq.OmsRabbitConstants; +import com.youlai.mall.oms.enums.OrderStatusEnum; +import com.youlai.mall.oms.pojo.entity.OrderEntity; +import com.youlai.mall.oms.pojo.entity.OrderGoodsEntity; +import com.youlai.mall.oms.service.OrderGoodsService; +import com.youlai.mall.oms.service.OrderRabbitService; +import com.youlai.mall.oms.service.OrderService; +import com.youlai.mall.pms.api.ProductFeignService; +import com.youlai.mall.pms.pojo.vo.SkuStockVO; +import com.youlai.mall.pms.pojo.vo.WareSkuStockVO; +import io.seata.spring.annotation.GlobalTransactional; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RabbitListener(queues = OmsRabbitConstants.ORDER_RELEASE_QUEUE) +@AllArgsConstructor +@Slf4j +public class OrderRabbitServiceImpl implements OrderRabbitService { + + private OrderService orderService; + + private OrderGoodsService orderGoodsService; + + private ProductFeignService productFeignService; + + /** + * 接收超时订单消息 + * 订单已支付 - 确认接收消息 + * 订单未支付 - 关闭订单,释放库存 + * 出现异常,消费消息失败,将数据重新放入队列,等待下次消费 + * + * @param orderSn + */ + @Override + @RabbitHandler + @GlobalTransactional(rollbackFor = Exception.class) + public void releaseOrder(String orderSn, Message message, Channel channel) { + long msgTag = message.getMessageProperties().getDeliveryTag(); + log.info("获取到消息,msgTag={},message={},body={}", msgTag, message.toString(), orderSn); + + try { + OrderEntity order = orderService.getByOrderSn(orderSn); + if (order.getStatus().equals(OrderStatusEnum.NEED_PAY.code)) { + if (orderService.closeOrderBySystem(orderSn)){ + releaseStock(order.getId()); + } + } + channel.basicAck(msgTag, false); + } catch (Exception e) { + log.error("关闭订单失败,orderSn={}", orderSn); + throw new BizException("关闭订单失败,orderSn=" + orderSn); + } + } + + private void releaseStock(Long orderId) { + List orderGoods = orderGoodsService.getByOrderId(orderId); + List items = orderGoods.stream().map(good -> { + SkuStockVO itemVO = new SkuStockVO(); + itemVO.setSkuId(good.getSkuId()); + itemVO.setNumber(good.getSkuQuantity()); + return itemVO; + }).collect(Collectors.toList()); + WareSkuStockVO wareSkuStock = new WareSkuStockVO(); + wareSkuStock.setItems(items); + Result result = productFeignService.releaseStock(wareSkuStock); + if (result == null || !StrUtil.equals(result.getCode(), ResultCode.SUCCESS.getCode())) { + log.error("释放库存异常,商品列表={}", items); + throw new BizException("关闭订单失败,释放库存错误"); + } + } +} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..ebec7ee72 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java @@ -0,0 +1,451 @@ +package com.youlai.mall.oms.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.base.Query; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.common.result.Result; +import com.youlai.common.result.ResultCode; +import com.youlai.common.utils.EnumUtils; +import com.youlai.common.web.exception.BizException; +import com.youlai.common.web.util.BeanMapperUtils; +import com.youlai.common.web.util.RequestUtils; +import com.youlai.mall.oms.config.rabbitmq.OmsRabbitConstants; +import com.youlai.mall.oms.dao.OrderDao; +import com.youlai.mall.oms.dao.OrderDeliveryDao; +import com.youlai.mall.oms.dao.OrderGoodsDao; +import com.youlai.mall.oms.enums.OrderStatusEnum; +import com.youlai.mall.oms.enums.OrderTypeEnum; +import com.youlai.mall.oms.pojo.entity.OrderDeliveryEntity; +import com.youlai.mall.oms.pojo.entity.OrderEntity; +import com.youlai.mall.oms.pojo.entity.OrderGoodsEntity; +import com.youlai.mall.oms.pojo.vo.*; +import com.youlai.mall.oms.service.CartService; +import com.youlai.mall.oms.service.OrderGoodsService; +import com.youlai.mall.oms.service.OrderLogsService; +import com.youlai.mall.oms.service.OrderService; +import com.youlai.mall.pms.api.ProductFeignService; +import com.youlai.mall.pms.pojo.vo.SkuInfoVO; +import com.youlai.mall.pms.pojo.vo.SkuStockVO; +import com.youlai.mall.pms.pojo.vo.WareSkuStockVO; +import com.youlai.mall.ums.api.MemberFeignService; +import com.youlai.mall.ums.pojo.dto.UmsAddressDTO; +import io.seata.spring.annotation.GlobalTransactional; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.function.Function; +import java.util.stream.Collectors; + +@AllArgsConstructor +@Slf4j +@Service("orderService") +public class OrderServiceImpl extends ServiceImpl implements OrderService { + + private static final ThreadLocal threadOrderSubmit = new ThreadLocal<>(); + + private CartService cartService; + + private ProductFeignService productFeignService; + + private MemberFeignService memberFeignService; + + private AsyncTaskExecutor executor; + + private OrderDao orderDao; + + private OrderGoodsDao orderGoodsDao; + + private OrderDeliveryDao orderDeliveryDao; + + private OrderLogsService orderLogsService; + + private OrderGoodsService orderGoodsService; + + private RabbitTemplate rabbitTemplate; + + @Override + public PageUtils queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return new PageUtils(page); + } + + @Override + public OrderConfirmVO confirm(String skuId, Integer number) { + List items = getOrderItemFromCart(skuId, number); + if (CollectionUtil.isEmpty(items)) { + log.info("订单商品列表为空,无法创建订单确认信息"); + return new OrderConfirmVO(); + } + + // feign调用商品接口,获取商品信息 + Map skuMap = new HashMap<>(items.size()); + List skuIds = items.stream().map(item -> item.getSkuId().toString()).collect(Collectors.toList()); + List skuInfos = productFeignService.infos(skuIds).getData(); + if (!CollectionUtil.isEmpty(skuInfos)) { + skuMap = skuInfos.stream().collect(Collectors.toMap(SkuInfoVO::getSkuId, Function.identity())); + } + + for (OrderItemVO item : items) { + SkuInfoVO info = skuMap.get(item.getSkuId()); + if (info != null) { + item.setPrice(info.getSkuPrice()); + item.setSkuImg(info.getSkuPic()); + item.setSkuName(info.getSkuName()); + } + } + + OrderConfirmVO confirm = new OrderConfirmVO(); + confirm.setItems(items); + return confirm; + } + + @Override + @GlobalTransactional + public OrderSubmitResultVO submit(OrderSubmitVO submit) throws ExecutionException, InterruptedException { + log.info("开始创建订单:{}", submit); + threadOrderSubmit.set(submit); + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + OrderVO orderVO = new OrderVO(); + CompletableFuture orderFuture = CompletableFuture.runAsync(() -> { + RequestContextHolder.setRequestAttributes(attributes); + threadOrderSubmit.set(submit); + OrderEntity order = createOrder(); + orderVO.setOrderEntity(order); + }, executor); + + CompletableFuture orderGoodsFuture = CompletableFuture.runAsync(() -> { + // 生成订单商品信息 + RequestContextHolder.setRequestAttributes(attributes); + threadOrderSubmit.set(submit); + List orderGoods = createOrderGoods(); + orderVO.setOrderGoods(orderGoods); + }, executor); + + CompletableFuture orderDeliveryFuture = CompletableFuture.runAsync(() -> { + threadOrderSubmit.set(submit); + RequestContextHolder.setRequestAttributes(attributes); + // 生成订单地址信息 + OrderDeliveryEntity orderDelivery = createOrderDelivery(); + if (orderDelivery == null) { + throw new BizException("提交订单失败,无法获取用户地址信息"); + } + orderVO.setOrderDeliveryEntity(orderDelivery); + }, executor); + + CompletableFuture future = CompletableFuture.allOf(orderFuture, orderGoodsFuture, orderDeliveryFuture); + future.get(); + + // 订单验价 + computePrice(orderVO.getOrderEntity(), orderVO.getOrderGoods()); + + // 扣减库存 + lockStock(orderVO.getOrderGoods()); + + // 保存订单 + this.baseMapper.insert(orderVO.getOrderEntity()); + Long orderId = orderVO.getOrderEntity().getId(); + + // 保存订单商品 + for (OrderGoodsEntity orderGood : orderVO.getOrderGoods()) { + orderGood.setOrderId(orderId); + orderGoodsDao.insert(orderGood); + } + + // 保存订单发货信息 + orderVO.getOrderDeliveryEntity().setOrderId(orderId); + orderDeliveryDao.insert(orderVO.getOrderDeliveryEntity()); + + // 保存订单日志 + // 清空购物车 + if (ObjectUtil.isNull(submit.getSkuId())) { + cartService.cleanSelected(); + } + + // 将订单放入定时队列中,超时未支付系统自动关单,是否库存 + rabbitTemplate.convertAndSend(OmsRabbitConstants.ORDER_EVENT_EXCHANGE, + OmsRabbitConstants.ORDER_CREATE_ORDER_KEY, orderVO.getOrderEntity().getOrderSn()); + + orderLogsService.addOrderLogs(orderVO.getOrderEntity().getId(), orderVO.getOrderEntity().getStatus(), RequestUtils.getUserId().toString(), "创建订单"); + + OrderSubmitResultVO result = new OrderSubmitResultVO(); + result.setId(orderId); + result.setOrderSn(orderVO.getOrderEntity().getOrderSn()); + return result; + } + + @Override + public OrderEntity getByOrderSn(String orderSn) { + log.info("根据订单号查询订单详情,orderSn={}", orderSn); + QueryWrapper query = new QueryWrapper<>(); + query.eq("order_sn", orderSn); + return baseMapper.selectOne(query); + } + + @Override + public boolean closeOrderBySystem(String orderSn) { + log.info("订单超时未支付,系统自动关闭,orderSn={}", orderSn); + OrderEntity order = getByOrderSn(orderSn); + if (!order.getStatus().equals(OrderStatusEnum.NEED_PAY.code)) { + log.info("订单状态异常,系统无法自动关闭,orderSn={},orderStatus={}", orderSn, order.getStatus()); + return false; + } + order.setStatus(OrderStatusEnum.SYS_CANCEL.code); + baseMapper.updateById(order); + // 添加订单操作日志 + orderLogsService.addOrderLogs(order.getId(), order.getStatus(), + "系统操作", OrderStatusEnum.SYS_CANCEL.desc); + return true; + + } + + @Override + public boolean cancelOrder(String id) { + log.info("会员取消订单,orderId={}", id); + OrderEntity order = getByOrderId(id); + if (!order.getStatus().equals(OrderStatusEnum.NEED_PAY.code)) { + log.info("订单状态异常,会员无法取消,orderId={},orderStatus={}", id, order.getStatus()); + return false; + } + order.setStatus(OrderStatusEnum.USER_CANCEL.code); + baseMapper.updateById(order); + // 添加订单操作日志 + orderLogsService.addOrderLogs(order.getId(), order.getStatus(), OrderStatusEnum.USER_CANCEL.desc); + return true; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteOrder(String id) { + // 查询订单,校验订单状态 + OrderEntity order = this.getByOrderId(id); + if (!order.getStatus().equals(OrderStatusEnum.SYS_CANCEL.code) && + order.getStatus().equals(OrderStatusEnum.USER_CANCEL.code)) { + throw new BizException(StrUtil.format("订单无法删除,订单状态【{}】", Objects.requireNonNull(EnumUtils.getByCode(order.getStatus(), OrderStatusEnum.class)).desc)); + } + + orderDao.deleteById(id); + orderLogsService.addOrderLogs(order.getId(), order.getStatus(), "会员删除订单"); + return true; + } + + @Override + public List list(Integer status) { + log.info("订单列表查询,status={}", status); + QueryWrapper orderQuery = new QueryWrapper<>(); + if (status != 0) { + orderQuery.eq("status", status); + } + orderQuery.orderByDesc("id"); + List orderList = this.list(orderQuery); + if (orderList == null || orderList.size() <= 0) { + log.info("订单列表查询结果为空,status={}", status); + return null; + } + + List orderIds = orderList.stream().map(orderEntity -> orderEntity.getId()).collect(Collectors.toList()); + Map> orderGoodsMap = orderGoodsService.getByOrderIds(orderIds); + List result = orderList.stream().map(orderEntity -> { + OrderListVO orderListVO = BeanMapperUtils.map(orderEntity, OrderListVO.class); + orderListVO.setStatusDesc(EnumUtils.getByCode(orderListVO.getStatus(), OrderStatusEnum.class).desc); + List orderGoodsEntities = orderGoodsMap.get(orderListVO.getId()); + if (orderGoodsEntities != null && orderGoodsEntities.size() > 0) { + List goodsListBeans = orderGoodsEntities.stream().map(orderGoodsEntity -> BeanMapperUtils.map(orderGoodsEntity, OrderListVO.GoodsListBean.class)).collect(Collectors.toList()); + orderListVO.setGoodsList(goodsListBeans); + } + return orderListVO; + }).collect(Collectors.toList()); + return result; + } + + @Override + public OrderEntity getByOrderId(String id) { + Long userId = RequestUtils.getUserId(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("member_id", userId).eq("id", id); + OrderEntity orderEntity = this.getOne(queryWrapper); + if (orderEntity == null) { + throw new BizException("订单不存在,订单id非法"); + } + return orderEntity; + } + + private void lockStock(List orderGoods) { + List items = orderGoods.stream().map(good -> { + SkuStockVO itemVO = new SkuStockVO(); + itemVO.setSkuId(good.getSkuId()); + itemVO.setNumber(good.getSkuQuantity()); + return itemVO; + }).collect(Collectors.toList()); + WareSkuStockVO wareSkuStock = new WareSkuStockVO(); + wareSkuStock.setItems(items); + Result result = productFeignService.lockStock(wareSkuStock); + if (result == null || !StrUtil.equals(result.getCode(), ResultCode.SUCCESS.getCode())) { + log.error("锁定库存异常,商品列表={}", items); + throw new BizException("下单失败,锁定库存错误"); + } + } + + + /** + * 计算订单商品价格 + * + * @param order + * @param orderGoods + * @return + */ + private Long computePrice(OrderEntity order, List orderGoods) { + log.info("计算订单价格:order:{},orderGoods:{}", order, orderGoods); + if (order == null || CollectionUtil.isEmpty(orderGoods)) { + throw new BizException("订单或订单商品列表为空,订单创建失败"); + } + Long totalAmount = orderGoods.stream().mapToLong(OrderGoodsEntity::getSkuTotalPrice).sum(); + int totalQuantity = orderGoods.stream().mapToInt(OrderGoodsEntity::getSkuQuantity).sum(); + Long payAmount = totalAmount; + if (order.getCouponAmount() != null) { + payAmount -= order.getCouponAmount(); + } + if (order.getFreightAmount() != null) { + payAmount -= order.getFreightAmount(); + } + order.setTotalAmount(totalAmount); + order.setTotalQuantity(totalQuantity); + order.setPayAmount(payAmount); + + OrderSubmitVO submit = threadOrderSubmit.get(); + if (!StrUtil.equals(submit.getPayAmount().toString(), payAmount.toString())) { + throw new BizException("订单价格变化,请重新提交"); + } + return payAmount; + + } + + /** + * 创建订单商品集合 + * + * @return + */ + private List createOrderGoods() { + OrderSubmitVO submit = threadOrderSubmit.get(); + log.info("创建订单商品实体类,submit:{}", submit); + List orderGoods = null; + if (ObjectUtil.isNull(submit.getSkuId())) { + CartVo detail = cartService.detail(); + log.info("从购物车中获取已选择商品信息:{}", detail); + orderGoods = detail.getItems().stream().map(item -> { + OrderGoodsEntity good = new OrderGoodsEntity(); + good.setSkuId(item.getSkuId()); + good.setSkuQuantity(item.getNumber()); + return good; + }).collect(Collectors.toList()); + } else { + log.info("会员选择商品直接下单,商品id:{}", submit.getSkuId()); + orderGoods = new ArrayList<>(); + OrderGoodsEntity good = new OrderGoodsEntity(); + good.setSkuId(Long.valueOf(submit.getSkuId())); + good.setSkuQuantity(submit.getSkuNumber()); + orderGoods.add(good); + } + + List skuIds = orderGoods.stream().map(vo -> vo.getSkuId().toString()).collect(Collectors.toList()); + Result> response = productFeignService.infos(skuIds); + List skuInfos = response.getData(); + if (skuInfos == null) { + return null; + } + Map skuMap = skuInfos.stream().collect(Collectors.toMap(SkuInfoVO::getSkuId, Function.identity(), (o1, o2) -> o2)); + for (OrderGoodsEntity good : orderGoods) { + SkuInfoVO skuInfo = skuMap.get(good.getSkuId()); + if (skuInfo == null) { + throw new BizException("订单商品库存为空"); + } + BeanMapperUtils.copy(skuInfo, good); + Long goodTotalPrice = good.getSkuPrice() * good.getSkuQuantity(); + good.setSkuTotalPrice(goodTotalPrice); + } + return orderGoods; + + } + + /** + * 生成订单数据 + * + * @return + */ + private OrderEntity createOrder() { + OrderSubmitVO submit = threadOrderSubmit.get(); + log.info("创建订单实体类,submit:{}", submit); + OrderEntity order = new OrderEntity(); + order.setOrderSn(IdWorker.getTimeId()); + order.setRemark(submit.getRemark()); + order.setStatus(OrderStatusEnum.NEED_PAY.code); + order.setSourceType(OrderTypeEnum.APP.code); + order.setMemberId(RequestUtils.getUserId()); + return order; + + } + + /** + * 获取订单地址信息 + * + * @return + */ + private OrderDeliveryEntity createOrderDelivery() { + String addressId = threadOrderSubmit.get().getAddressId(); + log.info("获取订单地址信息,addressId:{}", addressId); + try { + Result response = memberFeignService.getAddressById(addressId); + UmsAddressDTO addressInfo = response.getData(); + if (addressInfo != null) { + OrderDeliveryEntity delivery = new OrderDeliveryEntity(); + delivery.setReceiverProvince(addressInfo.getProvince()); + delivery.setReceiverCity(addressInfo.getCity()); + delivery.setReceiverRegion(addressInfo.getArea()); + delivery.setReceiverDetailAddress(addressInfo.getAddress()); + delivery.setReceiverName(addressInfo.getName()); + delivery.setReceiverPostCode(addressInfo.getZipCode()); + delivery.setReceiverPhone(addressInfo.getMobile()); + return delivery; + } + } catch (Exception e) { + log.error("获取订单地址信息失败,addressId:{}", addressId, e); + } + return null; + } + + /** + * 从购物车中获取订单商品列表 + * + * @return + */ + private List getOrderItemFromCart(String skuId, Integer number) { + if (!StrUtil.isEmpty(skuId)) { + log.info("请求携带商品id:{},数量:{},订单类型为用户直接购买", skuId, number); + OrderItemVO itemVO = OrderItemVO.builder().skuId(Long.parseLong(skuId)).number(number).build(); + return Arrays.asList(itemVO); + + } + CartVo cartVo = cartService.detail(); + List items = cartVo.getItems().stream().filter(CartItemVo::isChecked).map(cart -> OrderItemVO.builder().skuId(cart.getSkuId()).number(cart.getNumber()).build()).collect(Collectors.toList()); + return items; + } + +} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderSettingServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderSettingServiceImpl.java new file mode 100644 index 000000000..ffc752f5b --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderSettingServiceImpl.java @@ -0,0 +1,29 @@ +package com.youlai.mall.oms.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.common.base.Query; +import com.youlai.common.mybatis.utils.PageUtils; +import com.youlai.mall.oms.dao.OrderSettingDao; +import com.youlai.mall.oms.pojo.entity.OrderSettingEntity; +import com.youlai.mall.oms.service.OrderSettingService; +import org.springframework.stereotype.Service; + +import java.util.Map; + + +@Service("orderSettingService") +public class OrderSettingServiceImpl extends ServiceImpl implements OrderSettingService { + + @Override + public PageUtils queryPage(Map params) { + IPage page = this.page( + new Query().getPage(params), + new QueryWrapper() + ); + + return new PageUtils(page); + } + +} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/TokenServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/TokenServiceImpl.java new file mode 100644 index 000000000..08efff618 --- /dev/null +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/TokenServiceImpl.java @@ -0,0 +1,73 @@ +package com.youlai.mall.oms.service.impl; + +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.youlai.common.web.exception.BizException; +import com.youlai.common.web.util.RequestUtils; +import com.youlai.mall.oms.service.TokenService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +import static com.youlai.common.redis.constant.RedisKeyConstants.REDIS_KEY_TIME_OUT; +import static com.youlai.common.redis.constant.RedisKeyConstants.TOKEN_VERIFY; + +/** + * @author huawei + * @desc Token 服务 + * @email huawei_code@163.com + * @date 2021/1/21 + */ +@Service +@AllArgsConstructor +@Slf4j +public class TokenServiceImpl implements TokenService { + + private static final String TOKEN = "token"; + + private RedisTemplate redisTemplate; + + @Override + public String generateToken() { + StringBuffer sb = new StringBuffer(); + String userId = RequestUtils.getUserId().toString(); + //生成UUID + String token = IdUtil.randomUUID(); + //前缀 + 用户id + UUID组成 token + String key = sb.append(TOKEN_VERIFY).append(userId).append(':').append(token).toString(); + //将token写入redis并设置过期时间 + redisTemplate.opsForValue().set(key, key, REDIS_KEY_TIME_OUT); + //redis写入成功则设置token成功 + return token; + } + + @Override + public void checkToken(HttpServletRequest request) { + String token = request.getHeader(TOKEN); + if (StringUtils.isBlank(token)) { + token = request.getParameter(TOKEN); + if (StringUtils.isBlank(token)) { + throw new BizException("请勿重复提交"); + } + } + + StringBuilder sb = new StringBuilder(); + String userId = RequestUtils.getUserId().toString(); + String key = sb.append(TOKEN_VERIFY).append(userId).append(':').append(token).toString(); + + // 2、校验token是否存在 + if (!StrUtil.equals(redisTemplate.opsForValue().get(key).toString(), key)) { + log.debug("请求:{} 使用 token:{} 校验幂等性,缓存中不存在", request.getRequestURI(), token); + throw new BizException("请勿重复提交"); + } + // 3、校验token是否删除成功 + if (!redisTemplate.delete(key)) { + log.debug("请求:{} 使用 token:{} 校验幂等性,删除缓存数据失败", request.getRequestURI(), token); + throw new BizException("请勿重复提交"); + } + } +} diff --git a/mall-oms/oms-boot/src/main/resources/banner.txt b/mall-oms/oms-boot/src/main/resources/banner.txt new file mode 100644 index 000000000..944e74f81 --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/banner.txt @@ -0,0 +1,23 @@ +${AnsiColor.BRIGHT_RED} 升职加薪 +钱 ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⠀⠀⠀⠀⠀⠀ +多 ⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 身 +事 ⠸⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢙⢂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 强 +少 ⢸⣱⢄⣀⣀⣀⣀⣀ ⢀⣀⣠⢀⡀⣤⠤⣚⣼⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 体 +干 ⠀⠒⠿⣊⣇⣧⣾⣟⣝⣝⣿⣿⣜⡵⠵⢼⣊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 健 +的 ⠀⠀⠀⠐⠺⠿⣿⠻⢟⣿⢍⢍⢻⣿⣿⣧⡞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 进 +爽 ⠀⠀⠀⠀⠀⠀⣿⢠⣿⣿ ⣿⣴⣿⣿⣟⢷⣦⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 步 + ⠀⠀⠀⠀⠀⢸⢿⡿⢿⣿⣿⣿ ⢫⣿⠏⢤⣿⠩⣝⣷⣤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⣠⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 快 + ⠀⠀⠀⠀⠀⣏⡃⣘⣃⣿⠿⢛⣡⣿⠿⢶⣿⣿⣷⣬⣍⣼⡟⢻⣟⢟⠿⣿⠿⢛⣿⠿⣿⠿⢳⣶⣿⡿⠛⠛⠿⣷⣄⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠈⠉⠛⠛⠻⡿⡻⡉⠡⡀⣿⣿⣿⣿⣿⣿⣿⣷⣾⣬⣥⣴⣿⣗⣿⠡⣷⡗⣼⡷⠛⡻⣷⡀⠀⠀⠈⠻⣦⣀⠀⡔⠒⠲⡇ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡷⣷⡷⡿⣿⣿⣿⣿⣿⣿⣿⡍⠛⢛⢍⣽⠏⣼⠻⣜⣻⢟⣵⣷⠿⣿⢜⣧⠀⠀⠀⠀⠀⠉⠉⠑⠒⠊⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣮⣠⣠⣴⠿⣿⣿⣿⣿⣿⣿⣿⣾⣼⣾⡿⢧⣽⣎⠿⠻⣻⡵⢻⣿⠏⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣸⡟⢹⣗⣽⠿⣿⣿⣿⣿⣿⣿⡿⣆⣌⠐⣰⣿⣄⣛⣿⣻⠛⢍⣼⣋⣵⠣⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⡤⡲⣴⢄⣯⣬⣿⣷⣄⣹⠅⣱⣿⣿⣿⣿⣿⣿⠌⢽⣿⡟⠛⡋⣹⡝⣷⣉⣻⣏⣉⣲⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⠀⠀⠀⠀⢨⡪⡭⢸⣿⠃⠀⠉⠙⠛⠳⢼⣿⣿⣿⣿⢻⢊⣢⣽⣋⣿⣾⠾⣟⣯⣷⣿⡻⢿⣿⣿⣿⣿⣿⣦⡀⢠⣀⣤⠀⠀⠀⡀⠀⠀ + ⠀⠛⣠⣃⣬⣿⣁⠀⣿⣗⣤⠀⡀⠀⠀⣜⢿⣿⠏⠉⠋⠉⠉⠉⠉⠀⠀⠀⠙⠿⣿⣿⣧⠀⠈⠙⠛⠿⣿⣯⣼⠀⡃⣣⣧⣤⣾⣇⠀⠀ + ⢀⣀⣴⡿⣺⡏⢻⣆⡈⠓⠻⠃⡐⠀⠀⣷⣿⠋⠀⠀⠀⠀⠀⣼⣵⠇⡀⠀⠀⠀⣸⣿⡭⠃⠀⠀⠀⠀⠈⠻⣿⡄⠀⠿⣯⣖⡽⠃⠀⠀ + ⢨⣵⣭⣽⡗⡟⢿⣶⣿⡄⠀⠀⠀⠀⢠⣿⡇⠀⠀⠀⠙⡒⣥⣄⡘⠍⠀⢀⣠⣼⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⢹⣷⡀⠠⢵⠸⣤⣀⠀⠀ + ⠀⠉⢈⣋⣦⣴⡄⢉⣰⣲⡂⠀⠀⢰⣭⡽⠂⠀⠀⠀⠈⠀⠐⠻⢽⠿⡳⠶⡾⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣯⣵⠣⣟⣆⡃⠧⣾⡅⠀ + ⠀⠀⠙⠻⠿⠛⠉⠑⠋⠉⠀⠀⠪⣀⣉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠚⠀⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣱⣀⡁⠀⠀⠃ +${AnsiColor.BRIGHT_YELLOW}Spring Boot 版本:${spring-boot.version} +${AnsiColor.BRIGHT_YELLOW}项目名称:${spring.application.name} | 端口号:${server.port} \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/resources/bootstrap-dev.yml b/mall-oms/oms-boot/src/main/resources/bootstrap-dev.yml new file mode 100644 index 000000000..904e2403c --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/bootstrap-dev.yml @@ -0,0 +1,41 @@ +server: + port: 8603 + +spring: + application: + name: mall-oms + cloud: + nacos: + discovery: + server-addr: http://localhost:8848 + config: + server-addr: ${spring.cloud.nacos.discovery.server-addr} + file-extension: yaml + + + +# 全局参数设置 +ribbon: + ReadTimeout: 10000 + ConnectTimeout: 10000 + SocketTimeout: 10000 + MaxAutoRetries: 0 + MaxAutoRetriesNextServer: 1 + +# 分布式事务配置 +seata: + tx-service-group: mall_tx_group + enable-auto-data-source-proxy: true + registry: + type: nacos + nacos: + server-addr: c.youlai.store:8848 + namespace: seata_namespace_id + group: SEATA_GROUP + config: + type: nacos + nacos: + server-addr: c.youlai.store:8848 + namespace: seata_namespace_id + group: SEATA_GROUP + diff --git a/mall-oms/oms-boot/src/main/resources/bootstrap-prod.yml b/mall-oms/oms-boot/src/main/resources/bootstrap-prod.yml new file mode 100644 index 000000000..521f9ad73 --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/bootstrap-prod.yml @@ -0,0 +1,51 @@ +server: + port: 8603 + +spring: + application: + name: mall-oms + cloud: + nacos: + discovery: + server-addr: http://c.youlai.store:8848 + namespace: prod_namespace_id + config: + server-addr: ${spring.cloud.nacos.discovery.server-addr} + file-extension: yaml + namespace: prod_namespace_id + + +# 分布式事务配置 +seata: + tx-service-group: mall_tx_group + enable-auto-data-source-proxy: true + registry: + type: nacos + nacos: + server-addr: c.youlai.store:8848 + namespace: seata_namespace_id + group: SEATA_GROUP + config: + type: nacos + nacos: + server-addr: c.youlai.store:8848 + namespace: seata_namespace_id + group: SEATA_GROUP + + + +# 全局参数设置 +ribbon: + ReadTimeout: 10000 + ConnectTimeout: 10000 + SocketTimeout: 10000 + MaxAutoRetries: 0 + MaxAutoRetriesNextServer: 1 + + +# 站长支付API配置 +zzf: + AppKey: c35332f4d84646f7 + AppSecret: 1c93baadf7544f5faa5b5c6e02ef4307 + CreateOrderURL: https://admin.zhanzhangfu.com/order/createOrder + FindOrderURL: https://admin.zhanzhangfu.com/order/onlinePayFindResult diff --git a/mall-oms/oms-boot/src/main/resources/bootstrap.yml b/mall-oms/oms-boot/src/main/resources/bootstrap.yml new file mode 100644 index 000000000..3d7808a0c --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/bootstrap.yml @@ -0,0 +1,3 @@ +spring: + profiles: + active: dev diff --git a/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderDao.xml b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderDao.xml new file mode 100644 index 000000000..9c9d82fe2 --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderDao.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderDeliveryDao.xml b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderDeliveryDao.xml new file mode 100644 index 000000000..c93bd7a91 --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderDeliveryDao.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderGoodsDao.xml b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderGoodsDao.xml new file mode 100644 index 000000000..8e9897dba --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderGoodsDao.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderLogsDao.xml b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderLogsDao.xml new file mode 100644 index 000000000..e0816328e --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderLogsDao.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderPayDao.xml b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderPayDao.xml new file mode 100644 index 000000000..171beafe0 --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderPayDao.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderSettingDao.xml b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderSettingDao.xml new file mode 100644 index 000000000..39bd7f518 --- /dev/null +++ b/mall-oms/oms-boot/src/main/resources/mapper/oms/OrderSettingDao.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-oms/oms-boot/src/test/java/com/youlai/mall/oms/controller/OrderControllerTest.java b/mall-oms/oms-boot/src/test/java/com/youlai/mall/oms/controller/OrderControllerTest.java new file mode 100644 index 000000000..4e7068ca4 --- /dev/null +++ b/mall-oms/oms-boot/src/test/java/com/youlai/mall/oms/controller/OrderControllerTest.java @@ -0,0 +1,78 @@ +package com.youlai.mall.oms.controller; + +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.youlai.common.result.ResultCode; +import com.youlai.mall.oms.controller.admin.OrderController; +import com.youlai.mall.oms.pojo.OmsOrder; +import com.youlai.mall.oms.service.IOmsOrderService; +import com.youlai.mall.pms.api.ProductFeignService; +import com.youlai.mall.ums.api.MemberFeignService; +import io.seata.spring.annotation.GlobalTransactional; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + + +@AutoConfigureMockMvc +@SpringBootTest +@Slf4j +public class OrderControllerTest { + + @Autowired + public MockMvc mockMvc; + @Autowired + public OrderController orderController; + + + /** + * 提交订单 + * + * @throws Exception + */ + @Test + public void saveOrder() throws Exception { + + String goods = "{\"order\":{\"userId\":0,\"status\":10,\"source\":0,\"consignee\":\"str\",\"mobile\":\"str\",\"postcode\":\"str\",\"address\":\"str\",\"couponId\":0,\"skuPrice\":0,\"freightPrice\":0,\"couponPrice\":0,\"orderPrice\":0,\"integrationPrice\":0,\"payPrice\":0,\"payId\":\"str\",\"payType\":0,\"payTime\":1606379283562,\"shipSn\":\"str\",\"shipChannel\":\"str\"},\n" + + " \"orderItems\":[{\"spuId\":0,\"spuName\":\"str\",\"skuId\":\"0\",\"skuBarCode\":\"str\",\"skuSpecifications\":\"str\",\"skuPrice\":0,\"skuQuantity\":0,\"pic\":\"str\"}]}"; + MvcResult result = mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/orders") + .contentType("application/json") + .content(goods)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.code").value(ResultCode.SUCCESS.getCode())) + .andDo(print()) + .andReturn(); + + log.info(result.getResponse().getContentAsString()); + } + + + @Autowired + private ProductFeignService productFeignService; + + @Autowired + private MemberFeignService memberFeignService; + + @Autowired + private IOmsOrderService iOmsOrderService; + + + @Test + @GlobalTransactional(rollbackFor = Exception.class) + public void submitOrder() { + // 扣减库存 + productFeignService.updateStock(151l, -1); + // 增加积分 + memberFeignService.updatePoint(1l, 10); + // 修改订单状态 + iOmsOrderService.update(new LambdaUpdateWrapper().eq(OmsOrder::getId, 1l).set(OmsOrder::getStatus, 901)); + } +} diff --git a/mall-oms/pom.xml b/mall-oms/pom.xml index 73df08035..39f9759ca 100644 --- a/mall-oms/pom.xml +++ b/mall-oms/pom.xml @@ -14,7 +14,7 @@ pom oms-api - oms-biz + oms-boot diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/common/RedisConstants.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/common/RedisConstants.java new file mode 100644 index 000000000..5249ec680 --- /dev/null +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/common/RedisConstants.java @@ -0,0 +1,11 @@ +package com.youlai.mall.pms.common; + +/** + * @author haoxr + * @date 2021-02-28 20:10 + */ +public interface RedisConstants { + + String PRODUCT_INVENTORY_PREFIX = "product:inventory:"; + +} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/InventoryController.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/InventoryController.java new file mode 100644 index 000000000..3bde646fe --- /dev/null +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/InventoryController.java @@ -0,0 +1,46 @@ +package com.youlai.mall.pms.controller.app; + +import cn.hutool.core.bean.BeanUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.youlai.common.result.Result; +import com.youlai.mall.pms.pojo.domain.PmsSku; +import com.youlai.mall.pms.pojo.dto.SkuDTO; +import com.youlai.mall.pms.pojo.vo.SkuInfoVO; +import com.youlai.mall.pms.pojo.vo.WareSkuStockVO; +import com.youlai.mall.pms.service.IPmsSkuService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Api(tags = "【移动端】商品库存") +@RestController("AppInventoryController") +@RequestMapping("/api.app/v1/inventories") +@AllArgsConstructor +public class InventoryController { + + private IPmsSkuService iPmsSkuService; + + + @ApiOperation(value = "商品库存详情", httpMethod = "GET") + @ApiImplicitParam(name = "id", value = "商品SkuId", required = true, paramType = "path", dataType = "Long") + @GetMapping("/{id}") + public Result detail(@PathVariable Long id) { + PmsSku sku = iPmsSkuService.getById(id); + SkuDTO skuDTO = new SkuDTO(); + BeanUtil.copyProperties(sku, skuDTO); + return Result.success(skuDTO); + } + + + @ApiImplicitParam(name = "id", value = "商品SkuId", required = true, paramType = "path", dataType = "Long") + @GetMapping("/{skuId}/inventory") + public Result getInventoryBySkuId(@PathVariable Long skuId) { + Integer inventory = iPmsSkuService.getInventoryBySkuId(skuId); + return Result.success(inventory); + } +} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/SkuController.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/SkuController.java index dad3e493f..dbb3b9754 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/SkuController.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/SkuController.java @@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; @Api(tags = "【移动端】商品库存") -@RestController("AppInventoryController") +@RestController("AppSkuController") @RequestMapping("/api.app/v1/sku") @AllArgsConstructor public class SkuController { diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java index 5e6eccacb..09609efb4 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java @@ -29,4 +29,12 @@ public interface IPmsSkuService extends IService { * @return 释放库存结果 */ boolean releaseStock(WareSkuStockVO skuStockVO); + + + /** + * 获取商品库存 + * @param skuId + * @return + */ + Integer getInventoryBySkuId(Long skuId); } diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java index 067cc2466..b3b2bc1ff 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java @@ -1,14 +1,19 @@ package com.youlai.mall.pms.service.impl; +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.youlai.common.web.exception.BizException; +import com.youlai.mall.pms.common.RedisConstants; import com.youlai.mall.pms.mapper.PmsSkuMapper; import com.youlai.mall.pms.pojo.domain.PmsSku; import com.youlai.mall.pms.pojo.vo.SkuInfoVO; import com.youlai.mall.pms.pojo.vo.SkuStockVO; import com.youlai.mall.pms.pojo.vo.WareSkuStockVO; import com.youlai.mall.pms.service.IPmsSkuService; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -16,8 +21,12 @@ import java.util.List; @Service @Slf4j +@AllArgsConstructor public class PmsSkuServiceImpl extends ServiceImpl implements IPmsSkuService { + + private RedisTemplate redisTemplate; + @Override public List getSkuInfoByIds(List skuIds) { log.info("批量获取商品详情,skuIds:{}", skuIds); @@ -50,4 +59,37 @@ public class PmsSkuServiceImpl extends ServiceImpl impleme } return true; } + + + /** + * Cache-Aside pattern 缓存、数据库读写模式 + * 1. 读取数据,先读缓存,没有就去读数据库,然后将结果写入缓存 + * 2. 写入数据,先更新数据库,再删除缓存 + * @param skuId + * @return + */ + @Override + public Integer getInventoryBySkuId(Long skuId) { + Integer inventory = 0; + // 读->缓存 + Object cacheVal = redisTemplate.opsForValue().get(RedisConstants.PRODUCT_INVENTORY_PREFIX + skuId); + if (cacheVal != null) { + inventory = Convert.toInt(cacheVal); + return inventory; + } + + // 读->数据库 + PmsSku pmsInventory = this.getOne(new LambdaQueryWrapper() + .eq(PmsSku::getId, skuId) + .select(PmsSku::getStock)); + + if (pmsInventory != null) { + inventory = pmsInventory.getStock(); + // 写->缓存 + redisTemplate.opsForValue().set(RedisConstants.PRODUCT_INVENTORY_PREFIX + skuId, inventory); + } + + return inventory; + + } } diff --git a/youlai-common/common-core/src/main/java/com/youlai/common/constant/RedisConstants.java b/youlai-common/common-core/src/main/java/com/youlai/common/constant/RedisConstants.java new file mode 100644 index 000000000..3689fc3b4 --- /dev/null +++ b/youlai-common/common-core/src/main/java/com/youlai/common/constant/RedisConstants.java @@ -0,0 +1,7 @@ +package com.youlai.common.constant; + +public interface RedisConstants { + + String BUSINESS_NO_PREFIX = "business_no:"; + +} diff --git a/youlai-common/common-core/src/main/java/com/youlai/common/enums/BusinessTypeEnum.java b/youlai-common/common-core/src/main/java/com/youlai/common/enums/BusinessTypeEnum.java index 13b49f389..05a26912b 100644 --- a/youlai-common/common-core/src/main/java/com/youlai/common/enums/BusinessTypeEnum.java +++ b/youlai-common/common-core/src/main/java/com/youlai/common/enums/BusinessTypeEnum.java @@ -4,26 +4,29 @@ import lombok.Getter; import lombok.Setter; /** - * * @author haoxr * @date 2021-02-17 13:13 - * */ public enum BusinessTypeEnum { - USER("100", "用户类型编号"), - MEMBER("200", "会员类型编号"), - ORDER("300", "订单类型编号"); + USER("user", 100), + MEMBER("member", 200), + ORDER("order", 300); @Getter @Setter private String code; - BusinessTypeEnum(String code, String desc) { + @Getter + @Setter + private Integer value; + + BusinessTypeEnum(String code, Integer value) { this.code = code; + this.value = value; } - public static BusinessTypeEnum getValue(String code){ + public static BusinessTypeEnum getValue(String code) { for (BusinessTypeEnum value : values()) { if (value.getCode().equals(code)) { return value; diff --git a/youlai-common/common-redis/src/main/java/com/youlai/common/redis/component/BusinessNoGenerator.java b/youlai-common/common-redis/src/main/java/com/youlai/common/redis/component/BusinessNoGenerator.java index 840c93d4a..c9b955489 100644 --- a/youlai-common/common-redis/src/main/java/com/youlai/common/redis/component/BusinessNoGenerator.java +++ b/youlai-common/common-redis/src/main/java/com/youlai/common/redis/component/BusinessNoGenerator.java @@ -1,7 +1,7 @@ package com.youlai.common.redis.component; +import com.youlai.common.constant.RedisConstants; import com.youlai.common.enums.BusinessTypeEnum; -import com.youlai.common.redis.constant.RedisKeyConstants; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; @@ -20,22 +20,22 @@ public class BusinessNoGenerator { private RedisTemplate redisTemplate; /** - * @param businessCode 业务类型编号 + * @param businessType 业务类型枚举 * @param digit 业务序号位数 * @return */ - public String generate(String businessCode, Integer digit) { + public String generate(BusinessTypeEnum businessType, Integer digit) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); String date = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter); - String key = RedisKeyConstants.BUSINESS_NO_PREFIX + BusinessTypeEnum.getValue(businessCode).toString().toLowerCase() + ":" + date; + String key = RedisConstants.BUSINESS_NO_PREFIX +businessType.getCode() + ":" + date; Long increment = redisTemplate.opsForValue().increment(key); - return date + businessCode + String.format("%0" + digit + "d", increment); + return date + businessType.getValue() + String.format("%0" + digit + "d", increment); } - public String generate(String businessCode) { + public String generate(BusinessTypeEnum businessType) { Integer defaultDigit = 6; - return generate(businessCode, defaultDigit); + return generate(businessType, defaultDigit); } }