refactor(market):导入项目优惠卷模块初始工程
This commit is contained in:
parent
554aa38576
commit
d4c244701b
9
jzo2o-market/Dockerfile
Normal file
9
jzo2o-market/Dockerfile
Normal file
@ -0,0 +1,9 @@
|
||||
FROM openjdk:11-jdk
|
||||
LABEL maintainer="研究院研发组 <research-maint@itcast.cn>"
|
||||
RUN echo "Asia/Shanghai" > /etc/timezone
|
||||
ARG PACKAGE_PATH=./target/jzo2o-market.jar
|
||||
|
||||
ADD ${PACKAGE_PATH:-./} app.jar
|
||||
|
||||
EXPOSE 11510
|
||||
ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS app.jar"]
|
||||
103
jzo2o-market/pom.xml
Normal file
103
jzo2o-market/pom.xml
Normal file
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>jzo2o-market</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<artifactId>jzo2o-parent</artifactId>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-mvc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-knife4j-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-mysql</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--单元测试-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--canal-->
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-canal-sync</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-xxl-job</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>com.jzo2o</groupId>
|
||||
<artifactId>jzo2o-seata</artifactId>
|
||||
</dependency>-->
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-info</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>com.jzo2o.market.MarketApplication</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,20 @@
|
||||
package com.jzo2o.market;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
@EnableAspectJAutoProxy
|
||||
@SpringBootApplication
|
||||
@Slf4j
|
||||
@MapperScan("com.jzo2o.market.mapper")
|
||||
public class MarketApplication {
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(MarketApplication.class)
|
||||
.build(args)
|
||||
.run(args);
|
||||
log.info("家政服务-营销中心启动");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.jzo2o.market.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.GenericToStringSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
import org.springframework.scripting.support.ResourceScriptSource;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Configuration
|
||||
public class RedisLuaConfiguration {
|
||||
|
||||
@Bean("seizeCouponScript")
|
||||
public DefaultRedisScript<Integer> seizeCouponScript() {
|
||||
DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>();
|
||||
//resource目录下的scripts文件下的seizeCouponScript.lua文件
|
||||
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/seizeCouponScript.lua")));
|
||||
redisScript.setResultType(Integer.class);
|
||||
return redisScript;
|
||||
}
|
||||
|
||||
@Bean("lua_test01")
|
||||
public DefaultRedisScript<Integer> getLuaTest01() {
|
||||
DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>();
|
||||
//resource目录下的scripts文件下的lua_test01.lua文件
|
||||
redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("scripts/lua_test01.lua")));
|
||||
redisScript.setResultType(Integer.class);
|
||||
return redisScript;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package com.jzo2o.market.constants;
|
||||
|
||||
public class ErrorInfo {
|
||||
public static class Msg {
|
||||
public static final String SEIZE_COUPON_FAILD = "单子已经被抢走了";
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.jzo2o.market.constants;
|
||||
|
||||
public class RedisConstants {
|
||||
|
||||
public static final class RedisKey {
|
||||
/**
|
||||
* 优惠券库存表 由Canal同步程序写入
|
||||
* redis key格式:COUPON:RESOURCE:STOCK:{序号} 序号=活动id% 10
|
||||
* hash结构 (hashKey:活动id,hashValue:库存数量)
|
||||
*/
|
||||
public static final String COUPON_RESOURCE_STOCK = "COUPON:RESOURCE:STOCK:{%s}";
|
||||
|
||||
/**
|
||||
* 抢券同步队列,存储抢券成功记录由抢券程序(Lua)写入
|
||||
* redis key格式 QUEUE:COUPON:SEIZE:SYNC:{序号} 序号=活动id% 10
|
||||
* hash结构 (hashKey:活动id,hashValue:用户id)
|
||||
*/
|
||||
public static final String COUPON_SEIZE_SYNC_QUEUE_NAME = "COUPON:SEIZE:SYNC";
|
||||
|
||||
/**
|
||||
* 抢券成功列表,用户抢券成功写入记录
|
||||
* redis key格式 :COUPON:SEIZE:LIST:活动id_{序号} 序号=活动id% 10
|
||||
* hash结构 (hashKey:用户id,hashValue:1)
|
||||
*/
|
||||
public static final String COUPON_SEIZE_LIST = "COUPON:SEIZE:LIST:%s_{%s}";
|
||||
|
||||
/**
|
||||
* 活动列表 由于活动预热程序写入,待开始及进行中的活动
|
||||
* redis key格式:ACTIVITY:LIST
|
||||
* string 结构: value=活动列表json串
|
||||
*/
|
||||
public static final String ACTIVITY_CACHE_LIST = "ACTIVITY:LIST";
|
||||
}
|
||||
|
||||
public static final class Formatter {
|
||||
/**
|
||||
* 优惠券抢券同步
|
||||
*/
|
||||
public static final String COUPON_SEIZE_HANDLE_LOCK = "COUPON:SEIZE:RESULT_PROCESS";
|
||||
|
||||
/**
|
||||
* 活动预热
|
||||
*/
|
||||
public static final String ACTIVITY_PREHEAT = "ACTIVITY:PREHEAT";
|
||||
|
||||
/**
|
||||
* 活动结束
|
||||
*/
|
||||
public static final String ACTIVITY_FINISHED = "ACTIVITY:FINISHED";
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.jzo2o.market.constants;
|
||||
|
||||
public class TabTypeConstants {
|
||||
/**
|
||||
* 抢单中
|
||||
*/
|
||||
public static final int SEIZING = 1;
|
||||
|
||||
/**
|
||||
* 未开始
|
||||
*/
|
||||
public static final int NO_START = 2;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum ActivityStatusEnum {
|
||||
NO_DISTRIBUTE(1, "待生效"), DISTRIBUTING(2, "进行中"), LOSE_EFFICACY(3, "已失效"),VOIDED(4, "作废");
|
||||
private int status;
|
||||
private String name;
|
||||
|
||||
public boolean equals(Integer status) {
|
||||
return status != null && this.status == status;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.jzo2o.market.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum ActivityTypeEnum {
|
||||
AMOUNT_DISCOUNT(1, "满减"), RATE_DISCOUNT(2, "打折");
|
||||
|
||||
private int type;
|
||||
private String name;
|
||||
|
||||
public boolean equals(Integer type) {
|
||||
return type != null && type.equals(this.type);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.jzo2o.market.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum CouponStatusEnum {
|
||||
NO_USE(1, "未使用"), USED(2, "已使用"), INVALID(3, "已失效"),VOIDED(4,"已作废");
|
||||
private int status;
|
||||
private String name;
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.jzo2o.market.handler;
|
||||
|
||||
import com.jzo2o.market.service.IActivityService;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.redis.annotations.Lock;
|
||||
import com.jzo2o.redis.constants.RedisSyncQueueConstants;
|
||||
import com.jzo2o.redis.sync.SyncManager;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static com.jzo2o.market.constants.RedisConstants.Formatter.*;
|
||||
import static com.jzo2o.market.constants.RedisConstants.RedisKey.COUPON_SEIZE_SYNC_QUEUE_NAME;
|
||||
|
||||
@Component
|
||||
public class XxlJobHandler {
|
||||
|
||||
@Resource
|
||||
private SyncManager syncManager;
|
||||
|
||||
@Resource
|
||||
private IActivityService activityService;
|
||||
|
||||
@Resource
|
||||
private ICouponService couponService;
|
||||
|
||||
/**
|
||||
* 活动状态修改,
|
||||
* 1.活动进行中状态修改
|
||||
* 2.活动已失效状态修改
|
||||
* 1分钟一次
|
||||
*/
|
||||
@XxlJob("updateActivityStatus")
|
||||
public void updateActivitySatus(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 已领取优惠券自动过期任务
|
||||
*/
|
||||
@XxlJob("processExpireCoupon")
|
||||
public void processExpireCoupon() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.mapper;
|
||||
|
||||
import com.jzo2o.market.model.domain.Activity;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
public interface ActivityMapper extends BaseMapper<Activity> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.mapper;
|
||||
|
||||
import com.jzo2o.market.model.domain.Coupon;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
public interface CouponMapper extends BaseMapper<Coupon> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.mapper;
|
||||
|
||||
import com.jzo2o.market.model.domain.CouponUseBack;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券使用回退记录 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-18
|
||||
*/
|
||||
public interface CouponUseBackMapper extends BaseMapper<CouponUseBack> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.mapper;
|
||||
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券核销表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
public interface CouponWriteOffMapper extends BaseMapper<CouponWriteOff> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,119 @@
|
||||
package com.jzo2o.market.model.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class Activity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 优惠券配置id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.NONE)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 优惠券名称,可以和活动名称保持一致
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 使用类型,1:满减,2:折扣
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 使用条件,0:表示无门槛,其他值:最低消费金额
|
||||
*/
|
||||
private BigDecimal amountCondition;
|
||||
|
||||
/**
|
||||
* 折扣率,折扣类型的折扣率,8折就是存80
|
||||
*/
|
||||
private Integer discountRate;
|
||||
|
||||
/**
|
||||
* 优惠金额,满减或无门槛的优惠金额
|
||||
*/
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 优惠券有效期天数
|
||||
*/
|
||||
private Integer validityDays;
|
||||
|
||||
/**
|
||||
* 发放开始时间
|
||||
*/
|
||||
private LocalDateTime distributeStartTime;
|
||||
|
||||
/**
|
||||
* 发放结束时间
|
||||
*/
|
||||
private LocalDateTime distributeEndTime;
|
||||
|
||||
/**
|
||||
* 优惠券配置状态,1:待生效,2:进行中,3:已失效
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 发放数量,0:表示无限量,其他正数表示最大发放量
|
||||
*/
|
||||
private Integer totalNum;
|
||||
|
||||
/**
|
||||
* 库存数量
|
||||
*/
|
||||
private Integer stockNum;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 逻辑删除
|
||||
*/
|
||||
private Integer isDeleted;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
package com.jzo2o.market.model.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class Coupon implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 优惠券id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.NONE)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 优惠券名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 优惠券的拥有者
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户手机号
|
||||
*/
|
||||
private String userPhone;
|
||||
|
||||
/**
|
||||
* 活动id
|
||||
*/
|
||||
private Long activityId;
|
||||
|
||||
/**
|
||||
* 使用类型,1:满减,2:折扣
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
private Integer discountRate;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 满减金额
|
||||
*/
|
||||
private BigDecimal amountCondition;
|
||||
|
||||
/**
|
||||
* 有效期
|
||||
*/
|
||||
private LocalDateTime validityTime;
|
||||
|
||||
/**
|
||||
* 使用时间
|
||||
*/
|
||||
private LocalDateTime useTime;
|
||||
/**
|
||||
* 优惠券状态,1:未使用,2:已使用,3:已过期
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 订单id
|
||||
*/
|
||||
private String ordersId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
/**
|
||||
* 逻辑删除
|
||||
*/
|
||||
private Integer isDeleted;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.jzo2o.market.model.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券使用回退记录
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-18
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class CouponUseBack implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 回退记录id
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.NONE)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 优惠券id
|
||||
*/
|
||||
private Long couponId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 回退时间
|
||||
*/
|
||||
private LocalDateTime useBackTime;
|
||||
|
||||
/**
|
||||
* 核销时间
|
||||
*/
|
||||
private LocalDateTime writeOffTime;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.jzo2o.market.model.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券核销表
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CouponWriteOff implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.NONE)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 优惠券id
|
||||
*/
|
||||
private Long couponId;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 核销时使用的订单号
|
||||
*/
|
||||
private Long ordersId;
|
||||
|
||||
/**
|
||||
* 活动id
|
||||
*/
|
||||
private Long activityId;
|
||||
|
||||
/**
|
||||
* 核销时间
|
||||
*/
|
||||
private LocalDateTime writeOffTime;
|
||||
|
||||
/**
|
||||
* 核销人手机号
|
||||
*/
|
||||
private String writeOffManPhone;
|
||||
|
||||
/**
|
||||
* 核销人姓名
|
||||
*/
|
||||
private String writeOffManName;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.jzo2o.market.model.dto.request;
|
||||
|
||||
import com.jzo2o.common.model.dto.PageQueryDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel("活动分页查询模型")
|
||||
public class ActivityQueryForPageReqDTO extends PageQueryDTO {
|
||||
@ApiModelProperty("活动id")
|
||||
private Long id;
|
||||
@ApiModelProperty("活动名称")
|
||||
private String name;
|
||||
@ApiModelProperty("类型,,1:满减,2:折扣")
|
||||
private Integer type;
|
||||
@ApiModelProperty("优惠券配置状态,1:待生效,2:进行中,3:已失效")
|
||||
private Integer status;
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.jzo2o.market.model.dto.request;
|
||||
|
||||
import com.jzo2o.common.expcetions.BadRequestException;
|
||||
import com.jzo2o.common.utils.DateUtils;
|
||||
import com.jzo2o.common.utils.ObjectUtils;
|
||||
import com.jzo2o.market.enums.ActivityTypeEnum;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.checkerframework.checker.units.qual.Length;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.Null;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@ApiModel("活动保存请求模型")
|
||||
@Validated
|
||||
public class ActivitySaveReqDTO {
|
||||
@ApiModelProperty(value = "活动id,新增时不填,修改时必填",required = false)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "活动名称",required = true)
|
||||
@Size(max = 20, message = "活动名称超出20个字符无法输入")
|
||||
@Null(message = "活动名称为空,请输入活动名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "优惠券类型,1:满减,2:折扣",required = true)
|
||||
private Integer type;
|
||||
@ApiModelProperty(value = "满减限额,0:表示无门槛,其他值:最低消费金额")
|
||||
@Min(value = 0, message = "满额限制请输入大于/等于 0的整数")
|
||||
@Null(message = "满额限制为空,请输入满额限制")
|
||||
private BigDecimal amountCondition;
|
||||
|
||||
@ApiModelProperty(value = "折扣率,折扣类型的折扣率,例如:8,打8折, type为2时必填",required = false)
|
||||
private Integer discountRate;
|
||||
|
||||
@ApiModelProperty(value = "优惠金额,满减或无门槛的优惠金额",required = true)
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
@ApiModelProperty(value = "发放开始时间",required = true)
|
||||
@Null(message = "发放时间为空,请输入发放时间")
|
||||
private LocalDateTime distributeStartTime;
|
||||
@Null(message = "发放时间为空,请输入发放时间")
|
||||
@ApiModelProperty(value = "发放结束时间",required = true)
|
||||
private LocalDateTime distributeEndTime;
|
||||
|
||||
@ApiModelProperty(value = "发放数量,0:表示无限量,其他正数表示最大发放量",required = false)
|
||||
private Integer totalNum = 0;
|
||||
|
||||
@ApiModelProperty(value = "有效期天数",required = true)
|
||||
@Null(message = "使用期限请输入大于0的整数")
|
||||
@Min(value = 0, message = "使用期限请输入大于0的整数")
|
||||
private Integer validityDays;
|
||||
|
||||
public void check() {
|
||||
if(ActivityTypeEnum.AMOUNT_DISCOUNT.equals(type)) {
|
||||
// 满减
|
||||
//discountAmount字段不能为空,且值为正数
|
||||
if(ObjectUtils.isNull(discountAmount)) {
|
||||
throw new BadRequestException("折扣金额为空,请输入折扣金额");
|
||||
}else if(discountAmount.compareTo(BigDecimal.ZERO) <0){
|
||||
throw new BadRequestException("折扣金额请输入大于0的整数");
|
||||
}
|
||||
}else if(ActivityTypeEnum.RATE_DISCOUNT.equals(type)) {
|
||||
// 折扣
|
||||
if(ObjectUtils.isNull(discountRate)) {
|
||||
throw new BadRequestException("折扣比例为空,请输入折扣比例");
|
||||
}else if(discountRate.compareTo(0) < 0 || discountRate.compareTo(100) > 0) {
|
||||
throw new BadRequestException("折扣比例请输入大于0,小于10的整数");
|
||||
}
|
||||
}else {
|
||||
throw new BadRequestException("优惠券类型不存在");
|
||||
}
|
||||
// 发放时间
|
||||
if(distributeStartTime.isAfter(distributeEndTime)){
|
||||
throw new BadRequestException("结束时间不能早于开始时间");
|
||||
}
|
||||
if(distributeEndTime.isBefore(DateUtils.now())) {
|
||||
throw new BadRequestException("发放时间已过期");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.model.dto.request;
|
||||
|
||||
import com.jzo2o.common.model.dto.PageQueryDTO;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Null;
|
||||
|
||||
@Data
|
||||
@ApiModel("运营端优惠券查询模型")
|
||||
public class CouponOperationPageQueryReqDTO extends PageQueryDTO {
|
||||
@ApiModelProperty(value = "活动id",required = true)
|
||||
@Null(message = "请先选择活动")
|
||||
private Long activityId;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.jzo2o.market.model.dto.request;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Null;
|
||||
|
||||
@Data
|
||||
@ApiModel
|
||||
public class SeizeCouponReqDTO {
|
||||
@ApiModelProperty("活动id")
|
||||
@Null(message = "请求失败")
|
||||
private Long id;
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.jzo2o.market.model.dto.response;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@ApiModel("活动分页字段模型")
|
||||
public class ActivityInfoResDTO {
|
||||
@ApiModelProperty("活动id")
|
||||
private Long id;
|
||||
@ApiModelProperty("活动名称")
|
||||
private String name;
|
||||
@ApiModelProperty("优惠券类型,1:满减,2:折扣")
|
||||
private Integer type;
|
||||
@ApiModelProperty("满减限额,0:表示无门槛,其他值:最低消费金额")
|
||||
private BigDecimal amountCondition;
|
||||
@ApiModelProperty("折扣率,折扣类型的折扣率,例如:8,打8折")
|
||||
private Integer discountRate;
|
||||
@ApiModelProperty("优惠金额,满减或无门槛的优惠金额")
|
||||
private BigDecimal discountAmount;
|
||||
@ApiModelProperty("发放开始时间")
|
||||
private LocalDateTime distributeStartTime;
|
||||
@ApiModelProperty("发放结束时间")
|
||||
private LocalDateTime distributeEndTime;
|
||||
@ApiModelProperty("优惠券配置状态,1:待生效,2:进行中,3:已失效")
|
||||
private Integer status;
|
||||
@ApiModelProperty("发放数量,0:表示无限量,其他正数表示最大发放量")
|
||||
private Integer totalNum;
|
||||
@ApiModelProperty("领取数量")
|
||||
private Integer receiveNum;
|
||||
@ApiModelProperty("核销数量")
|
||||
private Integer writeOffNum;
|
||||
@ApiModelProperty("有效期天数")
|
||||
private Integer validityDays;
|
||||
@ApiModelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
@ApiModelProperty("更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
@ -0,0 +1,99 @@
|
||||
package com.jzo2o.market.model.dto.response;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
@Data
|
||||
public class CouponInfoResDTO implements Serializable {
|
||||
|
||||
@ApiModelProperty(value = "优惠券id",required = true)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 优惠券名称
|
||||
*/
|
||||
@ApiModelProperty(value = "活动名称",required = true)
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty("用户姓名")
|
||||
private String userName;
|
||||
|
||||
@ApiModelProperty("用户手机号")
|
||||
private String userPhone;
|
||||
|
||||
/**
|
||||
* 活动id
|
||||
*/
|
||||
@ApiModelProperty(value = "活动id",required = true)
|
||||
private Long activityId;
|
||||
|
||||
@ApiModelProperty(value = "使用类型,1:满减,2:折扣",required = true)
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
@ApiModelProperty(value = "折扣",required = false)
|
||||
private Integer discountRate;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
@ApiModelProperty(value = "优惠金额",required = false)
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
/**
|
||||
* 满减金额
|
||||
*/
|
||||
@ApiModelProperty(value = "满减条件,0:表示无门槛",required = true)
|
||||
private BigDecimal amountCondition;
|
||||
|
||||
/**
|
||||
* 有效期
|
||||
*/
|
||||
@ApiModelProperty("优惠券过期时间")
|
||||
private LocalDateTime validityTime;
|
||||
|
||||
@ApiModelProperty("使用时间")
|
||||
private LocalDateTime useTime;
|
||||
|
||||
/**
|
||||
* 优惠券状态,1:未使用,2:已使用,3:已过期
|
||||
*/
|
||||
@ApiModelProperty("优惠券状态,1:未使用,2:已使用,3:已过期")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 订单id
|
||||
*/
|
||||
private String ordersId;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ApiModelProperty(value = "创建时间",required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ApiModelProperty(value = "更新时间",required = true)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.jzo2o.market.model.dto.response;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@ApiModel("抢券列表信息")
|
||||
public class SeizeCouponInfoResDTO implements Serializable {
|
||||
@ApiModelProperty("活动id")
|
||||
private Long id;
|
||||
@ApiModelProperty("活动名称")
|
||||
private String name;
|
||||
@ApiModelProperty("优惠券类型,1:满减,2:折扣")
|
||||
private Integer type;
|
||||
@ApiModelProperty("满减限额,0:表示无门槛,其他值:最低消费金额")
|
||||
private BigDecimal amountCondition;
|
||||
@ApiModelProperty("折扣率,折扣类型的折扣率,例如:8,打8折")
|
||||
private Integer discountRate;
|
||||
@ApiModelProperty("优惠金额,满减或无门槛的优惠金额")
|
||||
private BigDecimal discountAmount;
|
||||
@ApiModelProperty("发放开始时间")
|
||||
private LocalDateTime distributeStartTime;
|
||||
@ApiModelProperty("发放结束时间")
|
||||
private LocalDateTime distributeEndTime;
|
||||
@ApiModelProperty("优惠券配置状态,1:待生效,2:进行中,3:已失效")
|
||||
private Integer status;
|
||||
@ApiModelProperty("优惠券剩余数量")
|
||||
private Integer remainNum;
|
||||
|
||||
@ApiModelProperty("发放数量")
|
||||
private Integer totalNum;
|
||||
@ApiModelProperty("库存数量")
|
||||
private Integer stockNum;
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package com.jzo2o.market.service;
|
||||
|
||||
import com.jzo2o.common.model.PageResult;
|
||||
import com.jzo2o.market.model.domain.Activity;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.jzo2o.market.model.dto.request.ActivityQueryForPageReqDTO;
|
||||
import com.jzo2o.market.model.dto.request.ActivitySaveReqDTO;
|
||||
import com.jzo2o.market.model.dto.response.ActivityInfoResDTO;
|
||||
import com.jzo2o.market.model.dto.response.SeizeCouponInfoResDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
public interface IActivityService extends IService<Activity> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.jzo2o.market.service;
|
||||
|
||||
import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import com.jzo2o.common.model.PageResult;
|
||||
import com.jzo2o.market.model.domain.Coupon;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.jzo2o.market.model.dto.request.CouponOperationPageQueryReqDTO;
|
||||
import com.jzo2o.market.model.dto.request.SeizeCouponReqDTO;
|
||||
import com.jzo2o.market.model.dto.response.CouponInfoResDTO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
public interface ICouponService extends IService<Coupon> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.jzo2o.market.service;
|
||||
|
||||
import com.jzo2o.market.model.domain.CouponUseBack;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券使用回退记录 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-18
|
||||
*/
|
||||
public interface ICouponUseBackService extends IService<CouponUseBack> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.jzo2o.market.service;
|
||||
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券核销表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
public interface ICouponWriteOffService extends IService<CouponWriteOff> {
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.jzo2o.market.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jzo2o.common.expcetions.BadRequestException;
|
||||
import com.jzo2o.common.model.PageResult;
|
||||
import com.jzo2o.common.utils.*;
|
||||
import com.jzo2o.market.constants.TabTypeConstants;
|
||||
import com.jzo2o.market.enums.ActivityStatusEnum;
|
||||
import com.jzo2o.market.mapper.ActivityMapper;
|
||||
import com.jzo2o.market.model.domain.Activity;
|
||||
import com.jzo2o.market.model.dto.request.ActivityQueryForPageReqDTO;
|
||||
import com.jzo2o.market.model.dto.request.ActivitySaveReqDTO;
|
||||
import com.jzo2o.market.model.dto.response.ActivityInfoResDTO;
|
||||
import com.jzo2o.market.model.dto.response.SeizeCouponInfoResDTO;
|
||||
import com.jzo2o.market.service.IActivityService;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.market.service.ICouponWriteOffService;
|
||||
import com.jzo2o.mysql.utils.PageUtils;
|
||||
import org.springframework.data.redis.core.HashOperations;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.jzo2o.market.constants.RedisConstants.RedisKey.*;
|
||||
import static com.jzo2o.market.enums.ActivityStatusEnum.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
@Service
|
||||
public class ActivityServiceImpl extends ServiceImpl<ActivityMapper, Activity> implements IActivityService {
|
||||
private static final int MILLION = 1000000;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
@Resource
|
||||
private ICouponService couponService;
|
||||
|
||||
@Resource
|
||||
private ICouponWriteOffService couponWriteOffService;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
package com.jzo2o.market.service.impl;
|
||||
|
||||
import cn.hutool.db.DbRuntimeException;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseBackReqDTO;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import com.jzo2o.common.expcetions.BadRequestException;
|
||||
import com.jzo2o.common.expcetions.CommonException;
|
||||
import com.jzo2o.common.expcetions.DBException;
|
||||
import com.jzo2o.common.model.PageResult;
|
||||
import com.jzo2o.common.utils.*;
|
||||
import com.jzo2o.market.enums.ActivityStatusEnum;
|
||||
import com.jzo2o.market.enums.CouponStatusEnum;
|
||||
import com.jzo2o.market.mapper.CouponMapper;
|
||||
import com.jzo2o.market.model.domain.Activity;
|
||||
import com.jzo2o.market.model.domain.Coupon;
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.jzo2o.market.model.dto.request.CouponOperationPageQueryReqDTO;
|
||||
import com.jzo2o.market.model.dto.request.SeizeCouponReqDTO;
|
||||
import com.jzo2o.market.model.dto.response.ActivityInfoResDTO;
|
||||
import com.jzo2o.market.model.dto.response.CouponInfoResDTO;
|
||||
import com.jzo2o.market.service.IActivityService;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.market.service.ICouponUseBackService;
|
||||
import com.jzo2o.market.service.ICouponWriteOffService;
|
||||
import com.jzo2o.market.utils.CouponUtils;
|
||||
import com.jzo2o.mvc.utils.UserContext;
|
||||
import com.jzo2o.mysql.utils.PageUtils;
|
||||
import com.jzo2o.redis.utils.RedisSyncQueueUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.jzo2o.common.constants.ErrorInfo.Code.SEIZE_COUPON_FAILD;
|
||||
import static com.jzo2o.market.constants.RedisConstants.RedisKey.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-16
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {
|
||||
|
||||
@Resource(name = "seizeCouponScript")
|
||||
private DefaultRedisScript<String> seizeCouponScript;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
@Resource
|
||||
private IActivityService activityService;
|
||||
|
||||
@Resource
|
||||
private ICouponUseBackService couponUseBackService;
|
||||
|
||||
@Resource
|
||||
private ICouponWriteOffService couponWriteOffService;
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package com.jzo2o.market.service.impl;
|
||||
|
||||
import com.jzo2o.common.utils.DateUtils;
|
||||
import com.jzo2o.common.utils.IdUtils;
|
||||
import com.jzo2o.market.model.domain.CouponUseBack;
|
||||
import com.jzo2o.market.mapper.CouponUseBackMapper;
|
||||
import com.jzo2o.market.service.ICouponUseBackService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券使用回退记录 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-18
|
||||
*/
|
||||
@Service
|
||||
public class CouponUseBackServiceImpl extends ServiceImpl<CouponUseBackMapper, CouponUseBack> implements ICouponUseBackService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.jzo2o.market.service.impl;
|
||||
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.jzo2o.market.mapper.CouponWriteOffMapper;
|
||||
import com.jzo2o.market.service.ICouponWriteOffService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券核销表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
@Service
|
||||
public class CouponWriteOffServiceImpl extends ServiceImpl<CouponWriteOffMapper, CouponWriteOff> implements ICouponWriteOffService {
|
||||
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.jzo2o.market.utils;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.jzo2o.market.enums.ActivityTypeEnum;
|
||||
import com.jzo2o.market.model.domain.Coupon;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
/**
|
||||
* 优惠券相关工具
|
||||
*/
|
||||
public class CouponUtils {
|
||||
|
||||
|
||||
}
|
||||
18
jzo2o-market/src/main/resources/bootstrap-dev.yml
Normal file
18
jzo2o-market/src/main/resources/bootstrap-dev.yml
Normal file
@ -0,0 +1,18 @@
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
username: nacos
|
||||
password: nacos
|
||||
server-addr: 192.168.122.135:8848
|
||||
config:
|
||||
namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63
|
||||
file-extension: yaml
|
||||
discovery:
|
||||
namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63
|
||||
ip: ${ACCESS_IP:}
|
||||
|
||||
################# 日志配置 #################
|
||||
logging:
|
||||
level:
|
||||
com.jzo2o: debug
|
||||
org.mongodb.driver: info
|
||||
14
jzo2o-market/src/main/resources/bootstrap-prod.yml
Normal file
14
jzo2o-market/src/main/resources/bootstrap-prod.yml
Normal file
@ -0,0 +1,14 @@
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
username: ${NACOS_USERNAME}
|
||||
password: ${NACOS_PASSWORD}
|
||||
server-addr: ${NACOS_ADDR}
|
||||
config:
|
||||
namespace: ${NACOS_NAMESPACE}
|
||||
file-extension: yaml
|
||||
discovery:
|
||||
namespace: ${NACOS_NAMESPACE}
|
||||
logging:
|
||||
level:
|
||||
com.jzo2o: debug
|
||||
14
jzo2o-market/src/main/resources/bootstrap-test.yml
Normal file
14
jzo2o-market/src/main/resources/bootstrap-test.yml
Normal file
@ -0,0 +1,14 @@
|
||||
spring:
|
||||
cloud:
|
||||
nacos:
|
||||
username: ${NACOS_USERNAME}
|
||||
password: ${NACOS_PASSWORD}
|
||||
server-addr: ${NACOS_ADDR}
|
||||
config:
|
||||
namespace: ${NACOS_NAMESPACE}
|
||||
file-extension: yaml
|
||||
discovery:
|
||||
namespace: ${NACOS_NAMESPACE}
|
||||
logging:
|
||||
level:
|
||||
com.jzo2o: debug
|
||||
76
jzo2o-market/src/main/resources/bootstrap.yml
Normal file
76
jzo2o-market/src/main/resources/bootstrap.yml
Normal file
@ -0,0 +1,76 @@
|
||||
################# 服务器配置 #################
|
||||
server:
|
||||
port: 11510
|
||||
undertow:
|
||||
accesslog:
|
||||
enabled: true
|
||||
pattern: "%t %a "%r" %s (%D ms)"
|
||||
dir: /data/logs/undertow/${spring.application.name}/access-logs/
|
||||
servlet:
|
||||
context-path: /market
|
||||
|
||||
################# spring公共配置 #################
|
||||
|
||||
spring:
|
||||
mvc:
|
||||
path-match:
|
||||
matching-strategy: ant_path_matcher
|
||||
format:
|
||||
date: yyyy-MM-dd HH:mm:ss
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: jzo2o-market
|
||||
main:
|
||||
# 支持循环依赖注入
|
||||
allow-circular-references: true
|
||||
# bean名相同覆盖
|
||||
allow-bean-definition-overriding: true
|
||||
cloud:
|
||||
nacos:
|
||||
username: ${NACOS_USERNAME}
|
||||
password: ${NACOS_PASSWORD}
|
||||
server-addr: ${NACOS_ADDR}
|
||||
discovery:
|
||||
namespace: ${NACOS_NAMESPACE}
|
||||
config:
|
||||
namespace: ${NACOS_NAMESPACE}
|
||||
file-extension: yaml
|
||||
shared-configs: # 共享配置
|
||||
- data-id: shared-redis-cluster.yaml # 共享redis集群配置
|
||||
refresh: false
|
||||
- data-id: shared-xxl-job.yaml # xxl-job配置
|
||||
refresh: false
|
||||
- data-id: shared-rabbitmq.yaml # rabbitmq配置
|
||||
refresh: false
|
||||
- data-id: shared-mysql.yaml # mysql配置
|
||||
refresh: false
|
||||
# - data-id: shared-spring-seata.yaml # seata
|
||||
# refresh: false
|
||||
|
||||
################# 项目独有配置 #################
|
||||
mysql:
|
||||
db-name: jzo2o-market
|
||||
mybatis:
|
||||
mapper-locations: mapper/*.xml
|
||||
type-aliases-package: com.jzo2o.market.mapper
|
||||
swagger:
|
||||
enable: true
|
||||
package-path: com.jzo2o.market.controller
|
||||
title: 家政服务-促销中心接口文档
|
||||
description: 用于活动优惠券的管理和使用
|
||||
contact-name: 传智教育·研究院
|
||||
contact-url: http://www.itcast.cn/
|
||||
contact-email: yjy@itcast.cn
|
||||
version: v1.0
|
||||
|
||||
################# 日志配置 #################
|
||||
logging:
|
||||
level:
|
||||
com.jzo2o: debug
|
||||
org.mongodb.driver: info
|
||||
feign:
|
||||
enable: true
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.jzo2o.market.mapper.ActivityMapper">
|
||||
|
||||
</mapper>
|
||||
5
jzo2o-market/src/main/resources/mapper/CouponMapper.xml
Normal file
5
jzo2o-market/src/main/resources/mapper/CouponMapper.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.jzo2o.market.mapper.CouponMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.jzo2o.market.mapper.CouponUseBackMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.jzo2o.market.mapper.CouponWriteOffMapper">
|
||||
|
||||
</mapper>
|
||||
@ -0,0 +1,37 @@
|
||||
-- 抢券lua实现
|
||||
-- key: 抢券同步队列,资源库存,抢券成功列表
|
||||
-- argv:活动id,用户id
|
||||
|
||||
--优惠券是否已经抢过
|
||||
local couponNum = redis.call("HGET", KEYS[3], ARGV[2])
|
||||
-- hget 获取不到数据返回false而不是nil
|
||||
if couponNum ~= false and tonumber(couponNum) >= 1
|
||||
then
|
||||
return "-1";
|
||||
end
|
||||
-- --库存是否充足校验
|
||||
local stockNum = redis.call("HGET",KEYS[2], ARGV[1])
|
||||
if stockNum == false or tonumber(stockNum) < 1
|
||||
then
|
||||
return "-2";
|
||||
end
|
||||
--抢券列表
|
||||
local listNum = redis.call("HSET",KEYS[3], ARGV[2], 1)
|
||||
if listNum == false or tonumber(listNum) < 1
|
||||
then
|
||||
return "-3";
|
||||
end
|
||||
|
||||
--减库存
|
||||
stockNum = redis.call("HINCRBY",KEYS[2], ARGV[1], -1)
|
||||
if tonumber(stockNum) < 0
|
||||
then
|
||||
return "-4"
|
||||
end
|
||||
-- 抢单结果写入同步队列
|
||||
local result = redis.call("HSETNX", KEYS[1], ARGV[2],ARGV[1])
|
||||
if result > 0
|
||||
then
|
||||
return ARGV[1] ..""
|
||||
end
|
||||
return "-5"
|
||||
Loading…
x
Reference in New Issue
Block a user