红包功能
This commit is contained in:
parent
668787f053
commit
f640fed356
@ -181,6 +181,8 @@ tenant:
|
|||||||
- sys_version
|
- sys_version
|
||||||
- ums_member_wechat
|
- ums_member_wechat
|
||||||
- sys_tenant_extend
|
- sys_tenant_extend
|
||||||
|
- red_packet
|
||||||
|
- red_packet_receive
|
||||||
- commission_template
|
- commission_template
|
||||||
- commission_rate_range
|
- commission_rate_range
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ public interface TenantConstants {
|
|||||||
/**
|
/**
|
||||||
* 超级管理员角色 roleKey
|
* 超级管理员角色 roleKey
|
||||||
*/
|
*/
|
||||||
String SUPER_ADMIN_ROLE_KEY = "superadmin";
|
String SUPER_ADMIN_ROLE_KEY = "superadmin";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 租户管理员角色 roleKey
|
* 租户管理员角色 roleKey
|
||||||
|
@ -22,6 +22,10 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
|
|||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
@ -101,6 +105,18 @@ public class RedisConfig {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||||
|
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||||
|
template.setConnectionFactory(redisConnectionFactory);
|
||||||
|
|
||||||
|
// 设置key的序列化方式
|
||||||
|
template.setKeySerializer(new StringRedisSerializer());
|
||||||
|
// 设置value的序列化方式
|
||||||
|
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
|
||||||
|
|
||||||
|
return template;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 异常处理器
|
* 异常处理器
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.wzj.soopin.member.domain.po;
|
package com.wzj.soopin.member.domain.po;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@ -19,7 +18,7 @@ import java.math.BigDecimal;
|
|||||||
@Schema(description="会员账户变动记录")
|
@Schema(description="会员账户变动记录")
|
||||||
@Data
|
@Data
|
||||||
@TableName("ums_account_change_record")
|
@TableName("ums_account_change_record")
|
||||||
@Builder(toBuilder = true)
|
@Builder
|
||||||
public class MemberAccountChangeRecord extends BaseAudit {
|
public class MemberAccountChangeRecord extends BaseAudit {
|
||||||
|
|
||||||
@Schema(description ="主键")
|
@Schema(description ="主键")
|
||||||
|
@ -7,6 +7,7 @@ import com.wzj.soopin.member.domain.bo.MemberAccountBO;
|
|||||||
import com.wzj.soopin.member.domain.po.MemberAccount;
|
import com.wzj.soopin.member.domain.po.MemberAccount;
|
||||||
import com.wzj.soopin.member.domain.vo.MemberAccountVO;
|
import com.wzj.soopin.member.domain.vo.MemberAccountVO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -18,5 +19,15 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface MemberAccountMapper extends BaseMapper<MemberAccount> {
|
public interface MemberAccountMapper extends BaseMapper<MemberAccount> {
|
||||||
IPage<MemberAccountVO> selectAccountWithMember(Page<?> page, @Param("bo") MemberAccountBO bo);
|
IPage<MemberAccountVO> selectAccountWithMember(Page<?> page, @Param("bo") MemberAccountBO bo);
|
||||||
|
|
||||||
|
@Select("SELECT money_balance \n" +
|
||||||
|
"FROM ums_account \n" +
|
||||||
|
"WHERE member_id = #{memberId};")
|
||||||
|
BigDecimal getMoneyBalanceByMemberId(Long memberId);
|
||||||
|
|
||||||
|
@Select("UPDATE ums_account \n" +
|
||||||
|
"SET money_balance = #{afterBalance} \n" +
|
||||||
|
"WHERE member_id = #{senderId};")
|
||||||
|
void updateMoneyBalance(Long senderId, BigDecimal afterBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,5 +172,14 @@
|
|||||||
<artifactId>wechatpay-apache-httpclient</artifactId>
|
<artifactId>wechatpay-apache-httpclient</artifactId>
|
||||||
<version>0.4.7</version>
|
<version>0.4.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
@ -172,7 +172,7 @@ public class OrderController extends BaseController {
|
|||||||
} else {
|
} else {
|
||||||
redisKey = "top_trading_products:" + java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
redisKey = "top_trading_products:" + java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
String jsonData = RedisUtils.getCacheObject(redisKey);
|
String jsonData = RedisUtils.getCacheObject(redisKey);
|
||||||
if (jsonData != null && !jsonData.isEmpty()) {
|
if (jsonData != null && !jsonData.isEmpty()) {
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.wzj.soopin.order.controller;
|
||||||
|
|
||||||
|
import com.wzj.soopin.order.domain.query.GrabRedPacketRequest;
|
||||||
|
import com.wzj.soopin.order.domain.query.SendRedPacketRequest;
|
||||||
|
import com.wzj.soopin.order.service.RedPacketService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.dromara.common.core.domain.R;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 红包功能控制器
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/red-packet")
|
||||||
|
@Api(tags = "红包功能接口")
|
||||||
|
public class RedPacketController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedPacketService redPacketService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发红包接口
|
||||||
|
* @param request 发红包请求参数
|
||||||
|
* @return 红包创建结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/send")
|
||||||
|
@ApiOperation("发红包")
|
||||||
|
public R<Map<String, Object>> sendRedPacket(@RequestBody SendRedPacketRequest request) {
|
||||||
|
Map<String, Object> result = redPacketService.sendRedPacket(request);
|
||||||
|
return R.ok("红包发送成功", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抢红包接口
|
||||||
|
* @return 抢红包结果
|
||||||
|
*/
|
||||||
|
@PostMapping("/grab")
|
||||||
|
@ApiOperation("抢红包")
|
||||||
|
public R<Map<String, Object>> grabRedPacket(@RequestBody GrabRedPacketRequest request) {
|
||||||
|
Map<String, Object> result = redPacketService.grabRedPacket(request);
|
||||||
|
return R.ok("红包领取成功", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 查询红包详情接口
|
||||||
|
// * @param packetId 红包ID
|
||||||
|
// * @return 红包详情
|
||||||
|
// */
|
||||||
|
// @GetMapping("/detail/{packetId}")
|
||||||
|
// @ApiOperation("查询红包详情")
|
||||||
|
// public R<RedPacketDetailVO> getRedPacketDetail(@PathVariable Long packetId) {
|
||||||
|
// RedPacketDetailVO detail = redPacketService.getRedPacketDetail(packetId);
|
||||||
|
// return R.ok(detail);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 查询用户领取的红包记录
|
||||||
|
// * @param userId 用户ID
|
||||||
|
// * @param pageNum 页码
|
||||||
|
// * @param pageSize 每页条数
|
||||||
|
// * @return 领取记录列表
|
||||||
|
// */
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.wzj.soopin.order.domain.entity;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import org.dromara.common.core.domain.model.BaseAudit;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "红包实体")
|
||||||
|
public class RedPacket extends BaseAudit {
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
@Schema(description = "红包id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@TableField("sender_id")
|
||||||
|
@Schema(description = "发送人id")
|
||||||
|
private Long senderId;
|
||||||
|
|
||||||
|
@TableField("chat_type")
|
||||||
|
@Schema(description = "聊天类型(1:单聊 2:群聊)")
|
||||||
|
private Integer chatType;
|
||||||
|
|
||||||
|
@TableField("receiver_id")
|
||||||
|
@Schema(description = "接收者ID(单聊)")
|
||||||
|
private Long receiverId;
|
||||||
|
|
||||||
|
@TableField("group_id")
|
||||||
|
@Schema(description = "群id")
|
||||||
|
private Long groupId;
|
||||||
|
|
||||||
|
@TableField("packet_type")
|
||||||
|
@Schema(description = "红包类型(1:普通)")
|
||||||
|
private Integer packetType;
|
||||||
|
|
||||||
|
@TableField("total_amount")
|
||||||
|
@Schema(description = "总金额")
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
@TableField("total_count")
|
||||||
|
@Schema(description = "总个数")
|
||||||
|
private Integer totalCount;
|
||||||
|
|
||||||
|
@TableField("remaining_amount")
|
||||||
|
@Schema(description = "剩余金额")
|
||||||
|
private BigDecimal remainingAmount;
|
||||||
|
|
||||||
|
@TableField("remaining_count")
|
||||||
|
@Schema(description = "剩余个数")
|
||||||
|
private Integer remainingCount;
|
||||||
|
|
||||||
|
@TableField("status")
|
||||||
|
@Schema(description = "状态(0:未领取 1:已领取部分 2:已领完 3:已过期 4:已退款)")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@TableField("expire_time")
|
||||||
|
@Schema(description = "过期时间")
|
||||||
|
private LocalDateTime expireTime;
|
||||||
|
|
||||||
|
@TableField("remark")
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.wzj.soopin.order.domain.entity;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import lombok.Data;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "红包领取记录实体")
|
||||||
|
public class RedPacketReceive {
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
@Schema(description = "主键ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@TableField("packet_id")
|
||||||
|
@Schema(description = "红包id")
|
||||||
|
private Long packetId;
|
||||||
|
|
||||||
|
@TableField("receiver_id")
|
||||||
|
@Schema(description = "领取者id")
|
||||||
|
private Long receiverId;
|
||||||
|
|
||||||
|
@TableField("amount")
|
||||||
|
@Schema(description = "领取金额")
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
@TableField("recevice_time")
|
||||||
|
@Schema(description = "领取时间")
|
||||||
|
private DateTime receviceTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.wzj.soopin.order.domain.form;
|
||||||
|
|
||||||
|
import com.wzj.soopin.order.domain.dto.OrderProductListDTO;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class OrderSubmitForm {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Long addressId;
|
||||||
|
private String note;
|
||||||
|
/** 支付方式 0:未支付 1:支付宝 2:微信 默认微信 */
|
||||||
|
private Integer payType = 2;
|
||||||
|
/** 订单来源,购物车则为cart */
|
||||||
|
private String from;
|
||||||
|
private Long memberCouponId;
|
||||||
|
@NotEmpty
|
||||||
|
private List<OrderProductListDTO> skuList;
|
||||||
|
@Data
|
||||||
|
public static class SkuParam {
|
||||||
|
private Long skuId;
|
||||||
|
private Integer quantity;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.wzj.soopin.order.domain.query;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抢红包请求参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "抢红包请求参数")
|
||||||
|
public class GrabRedPacketRequest {
|
||||||
|
|
||||||
|
@Schema(description = "红包id")
|
||||||
|
private Long packetId;
|
||||||
|
|
||||||
|
@Schema(description = "用户id")
|
||||||
|
private Long memberId;
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.wzj.soopin.order.domain.query;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.DecimalMin;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.validator.constraints.Range;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发红包请求参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "发红包请求参数")
|
||||||
|
public class SendRedPacketRequest {
|
||||||
|
|
||||||
|
@NotNull(message = "聊天类型不能为空")
|
||||||
|
@Range(min = 1, max = 2, message = "聊天类型只能是1(单聊)或2(群聊)")
|
||||||
|
@Schema(description = "聊天类型(1:单聊 2:群聊)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Integer chatType;
|
||||||
|
|
||||||
|
@NotNull(message = "发送者ID不能为空")
|
||||||
|
@Schema(description = "发送者ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Long senderId;
|
||||||
|
|
||||||
|
@Schema(description = "接收者ID(单聊时必填)")
|
||||||
|
private Long receiverId;
|
||||||
|
|
||||||
|
@Schema(description = "群id(群聊时必填)")
|
||||||
|
private Long groupId;
|
||||||
|
|
||||||
|
@NotNull(message = "红包类型不能为空")
|
||||||
|
@Range(min = 1, max = 2, message = "红包类型只能是1(普通)或2(拼手气)")
|
||||||
|
@Schema(description = "红包类型(1:普通 2:拼手气)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Integer packetType;
|
||||||
|
|
||||||
|
@NotNull(message = "总金额不能为空")
|
||||||
|
@DecimalMin(value = "0.01", message = "总金额不能小于0.01")
|
||||||
|
@Schema(description = "总金额", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
@NotNull(message = "总个数不能为空")
|
||||||
|
@Min(value = 1, message = "总个数不能小于1")
|
||||||
|
@Schema(description = "总个数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
|
private Integer totalCount;
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "备注(祝福语)")
|
||||||
|
private String remark;
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.wzj.soopin.order.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.wzj.soopin.order.domain.entity.RedPacket;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface RedPacketMapper extends BaseMapper<RedPacket> {
|
||||||
|
|
||||||
|
@Select("SELECT * FROM red_packet WHERE expire_time < NOW() AND status IN (0, 1)")
|
||||||
|
List<RedPacket> selectExpiredRedPackets();
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.wzj.soopin.order.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.wzj.soopin.order.domain.entity.RedPacketReceive;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
public interface RedPacketReceiveMapper extends BaseMapper<RedPacketReceive> {
|
||||||
|
|
||||||
|
@Select("SELECT COUNT(1) FROM red_packet_receive " +
|
||||||
|
"WHERE packet_id = #{packetId} " +
|
||||||
|
"AND receiver_id = #{memberId} ")
|
||||||
|
Integer checkReceived(Long packetId, Long memberId);
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.wzj.soopin.order.service;
|
||||||
|
|
||||||
|
import com.wzj.soopin.order.domain.query.GrabRedPacketRequest;
|
||||||
|
import com.wzj.soopin.order.domain.query.SendRedPacketRequest;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface RedPacketService {
|
||||||
|
|
||||||
|
Map<String, Object> sendRedPacket(SendRedPacketRequest request);
|
||||||
|
|
||||||
|
Map<String, Object> grabRedPacket(GrabRedPacketRequest request);
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package com.wzj.soopin.order.service.impl;
|
package com.wzj.soopin.order.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
@ -10,29 +8,24 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
|
|
||||||
import com.wzj.soopin.goods.domain.entity.Sku;
|
import com.wzj.soopin.goods.domain.entity.Sku;
|
||||||
import com.wzj.soopin.goods.mapper.SkuMapper;
|
import com.wzj.soopin.goods.mapper.SkuMapper;
|
||||||
import com.wzj.soopin.member.domain.po.Member;
|
import com.wzj.soopin.member.domain.po.Member;
|
||||||
import com.wzj.soopin.member.domain.po.MemberWechat;
|
|
||||||
import com.wzj.soopin.member.mapper.*;
|
import com.wzj.soopin.member.mapper.*;
|
||||||
import com.wzj.soopin.order.domain.bo.OrderBo;
|
import com.wzj.soopin.order.domain.bo.OrderBo;
|
||||||
import com.wzj.soopin.order.domain.entity.*;
|
import com.wzj.soopin.order.domain.entity.*;
|
||||||
import com.wzj.soopin.order.domain.form.DeliverProductForm;
|
import com.wzj.soopin.order.domain.form.DeliverProductForm;
|
||||||
import com.wzj.soopin.order.domain.form.ManagerOrderQueryForm;
|
import com.wzj.soopin.order.domain.form.ManagerOrderQueryForm;
|
||||||
import com.wzj.soopin.order.domain.form.OrderPayForm;
|
|
||||||
import com.wzj.soopin.order.domain.query.OrderH5Query;
|
import com.wzj.soopin.order.domain.query.OrderH5Query;
|
||||||
import com.wzj.soopin.order.domain.vo.*;
|
import com.wzj.soopin.order.domain.vo.*;
|
||||||
import com.wzj.soopin.order.mapper.*;
|
import com.wzj.soopin.order.mapper.*;
|
||||||
import com.wzj.soopin.order.service.OrderService;
|
import com.wzj.soopin.order.service.OrderService;
|
||||||
import com.wzj.soopin.order.service.VerificationCodeService;
|
import com.wzj.soopin.order.service.VerificationCodeService;
|
||||||
import com.wzj.soopin.order.wechat.WechatPayData;
|
|
||||||
import com.wzj.soopin.order.wechat.WechatPayService;
|
import com.wzj.soopin.order.wechat.WechatPayService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.common.core.domain.R;
|
import org.dromara.common.core.domain.R;
|
||||||
import org.dromara.common.core.domain.event.Constants;
|
import org.dromara.common.core.domain.event.Constants;
|
||||||
import org.dromara.common.core.enums.OrderStatus;
|
|
||||||
import org.dromara.common.core.utils.PhoneUtils;
|
import org.dromara.common.core.utils.PhoneUtils;
|
||||||
import org.dromara.common.core.utils.SecurityUtils;
|
import org.dromara.common.core.utils.SecurityUtils;
|
||||||
import org.dromara.common.redis.redis.RedisService;
|
import org.dromara.common.redis.redis.RedisService;
|
||||||
@ -46,16 +39,12 @@ import org.springframework.beans.BeanUtils;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单表Service业务层处理
|
* 订单表Service业务层处理
|
||||||
@ -558,10 +547,5 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,386 @@
|
|||||||
|
package com.wzj.soopin.order.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateTime;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.wzj.soopin.member.domain.po.MemberAccountChangeRecord;
|
||||||
|
import com.wzj.soopin.member.mapper.MemberAccountChangeRecordMapper;
|
||||||
|
import com.wzj.soopin.member.mapper.MemberAccountMapper;
|
||||||
|
import com.wzj.soopin.order.domain.entity.RedPacket;
|
||||||
|
import com.wzj.soopin.order.domain.entity.RedPacketReceive;
|
||||||
|
import com.wzj.soopin.order.domain.query.GrabRedPacketRequest;
|
||||||
|
import com.wzj.soopin.order.domain.query.SendRedPacketRequest;
|
||||||
|
import com.wzj.soopin.order.mapper.RedPacketMapper;
|
||||||
|
import com.wzj.soopin.order.mapper.RedPacketReceiveMapper;
|
||||||
|
import com.wzj.soopin.order.service.RedPacketService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RedPacketServiceImpl extends ServiceImpl<RedPacketMapper, RedPacket> implements RedPacketService {
|
||||||
|
|
||||||
|
private final RedPacketMapper redPacketMapper;
|
||||||
|
private final RedPacketReceiveMapper redPacketReceiveMapper;
|
||||||
|
private final MemberAccountMapper umsAccountMapper;
|
||||||
|
private final MemberAccountChangeRecordMapper accountChangeRecordMapper;
|
||||||
|
private final RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
// Redis锁前缀
|
||||||
|
private static final String LOCK_PREFIX = "red_packet:lock:";
|
||||||
|
|
||||||
|
// 红包状态:0-未领取 1-已领取部分 2-已领完 3-已过期 4-已退款
|
||||||
|
private static final int STATUS_UNRECEIVED = 0;
|
||||||
|
private static final int STATUS_PART_RECEIVED = 1;
|
||||||
|
private static final int STATUS_ALL_RECEIVED = 2;
|
||||||
|
private static final int STATUS_EXPIRED = 3;
|
||||||
|
private static final int STATUS_REFUNDED = 4;
|
||||||
|
|
||||||
|
// 聊天类型:1-单聊 2-群聊
|
||||||
|
private static final int CHAT_TYPE_SINGLE = 1;
|
||||||
|
private static final int CHAT_TYPE_GROUP = 2;
|
||||||
|
|
||||||
|
// 金额变动类型:100-发红包扣钱 101-领红包加钱 102-红包退款
|
||||||
|
private static final int CHANGE_TYPE_SEND = 100;
|
||||||
|
private static final int CHANGE_TYPE_RECEIVE = 101;
|
||||||
|
private static final int CHANGE_TYPE_REFUND = 102;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> sendRedPacket(SendRedPacketRequest request) {
|
||||||
|
// 参数校验
|
||||||
|
validateSendParams(request);
|
||||||
|
|
||||||
|
Long memberId = request.getSenderId();
|
||||||
|
|
||||||
|
// 验证发送者余额
|
||||||
|
BigDecimal balance = umsAccountMapper.getMoneyBalanceByMemberId(memberId);
|
||||||
|
if (balance == null || balance.compareTo(request.getTotalAmount()) < 0) {
|
||||||
|
throw new RuntimeException("账户余额不足,无法发送红包");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建红包记录
|
||||||
|
RedPacket redPacket = createRedPacket(request);
|
||||||
|
redPacketMapper.insert(redPacket);
|
||||||
|
Long packetId = redPacket.getId();
|
||||||
|
|
||||||
|
// 扣减发送者余额并记录变动
|
||||||
|
deductSenderBalance(request.getSenderId(), redPacket, balance);
|
||||||
|
|
||||||
|
// 返回结果
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("packetId", packetId);
|
||||||
|
result.put("receiverId", redPacket.getReceiverId());
|
||||||
|
result.put("totalAmount", redPacket.getTotalAmount());
|
||||||
|
result.put("totalCount", redPacket.getTotalCount());
|
||||||
|
result.put("createTime", redPacket.getCreateTime());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> grabRedPacket(GrabRedPacketRequest request) {
|
||||||
|
|
||||||
|
Long packetId = request.getPacketId();
|
||||||
|
Long memberId = request.getMemberId();
|
||||||
|
// 获取分布式锁
|
||||||
|
String lockKey = LOCK_PREFIX + packetId;
|
||||||
|
Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS);
|
||||||
|
if (Boolean.TRUE.equals(locked)) {
|
||||||
|
try {
|
||||||
|
return doReceiveRedPacket(packetId, memberId);
|
||||||
|
} finally {
|
||||||
|
// 释放锁
|
||||||
|
redisTemplate.delete(lockKey);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("抢红包太火爆,请稍后再试");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public Map<String, Object> doReceiveRedPacket(Long packetId, Long memberId) {
|
||||||
|
// 查询红包信息
|
||||||
|
RedPacket redPacket = redPacketMapper.selectById(packetId);
|
||||||
|
if (redPacket == null) {
|
||||||
|
throw new RuntimeException("红包不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证红包状态
|
||||||
|
validateRedPacketStatus(redPacket, memberId);
|
||||||
|
|
||||||
|
// 检查是否已领取
|
||||||
|
Integer received = redPacketReceiveMapper.checkReceived(packetId, memberId);
|
||||||
|
if (received != null && received > 0) {
|
||||||
|
throw new RuntimeException("您已领取过该红包");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算领取金额
|
||||||
|
BigDecimal receiveAmount = calculateReceiveAmount(redPacket);
|
||||||
|
|
||||||
|
// 更新红包剩余金额和数量
|
||||||
|
updateRedPacketRemaining(redPacket, receiveAmount);
|
||||||
|
|
||||||
|
// 创建领取记录
|
||||||
|
RedPacketReceive receiveRecord = createReceiveRecord(redPacket, memberId, receiveAmount);
|
||||||
|
redPacketReceiveMapper.insert(receiveRecord);
|
||||||
|
|
||||||
|
// 增加领取者余额并记录变动
|
||||||
|
addReceiverBalance(memberId, receiveAmount, packetId);
|
||||||
|
|
||||||
|
// 更新红包状态
|
||||||
|
updateRedPacketStatus(redPacket);
|
||||||
|
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
result.put("packetId", packetId);
|
||||||
|
result.put("receiveAmount", receiveAmount);
|
||||||
|
result.put("receiveTime", receiveRecord.getReceviceTime());
|
||||||
|
result.put("isLastOne", redPacket.getRemainingCount() == 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证发送红包参数
|
||||||
|
*/
|
||||||
|
private void validateSendParams(SendRedPacketRequest request) {
|
||||||
|
// 验证聊天类型
|
||||||
|
if (request.getChatType() != CHAT_TYPE_SINGLE && request.getChatType() != CHAT_TYPE_GROUP) {
|
||||||
|
throw new RuntimeException("聊天类型无效,只能是单聊或群聊");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单聊必须指定接收者
|
||||||
|
if (request.getChatType() == CHAT_TYPE_SINGLE && request.getReceiverId() == null) {
|
||||||
|
throw new RuntimeException("单聊红包必须指定接收者ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 群聊必须指定群ID和红包个数
|
||||||
|
if (request.getChatType() == CHAT_TYPE_GROUP) {
|
||||||
|
if (request.getGroupId() == null) {
|
||||||
|
throw new RuntimeException("群聊红包必须指定群ID");
|
||||||
|
}
|
||||||
|
if (request.getTotalCount() == null || request.getTotalCount() < 1) {
|
||||||
|
throw new RuntimeException("群聊红包必须指定有效个数(至少1个)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建红包记录
|
||||||
|
*/
|
||||||
|
private RedPacket createRedPacket(SendRedPacketRequest request) {
|
||||||
|
RedPacket redPacket = new RedPacket();
|
||||||
|
redPacket.setSenderId(request.getSenderId());
|
||||||
|
redPacket.setChatType(request.getChatType());
|
||||||
|
redPacket.setReceiverId(request.getReceiverId());
|
||||||
|
redPacket.setGroupId(request.getGroupId());
|
||||||
|
// 默认为普通红包
|
||||||
|
redPacket.setPacketType(1);
|
||||||
|
redPacket.setTotalAmount(request.getTotalAmount());
|
||||||
|
redPacket.setTotalCount(request.getTotalCount());
|
||||||
|
redPacket.setRemainingAmount(request.getTotalAmount());
|
||||||
|
redPacket.setRemainingCount(request.getTotalCount());
|
||||||
|
redPacket.setStatus(STATUS_UNRECEIVED);
|
||||||
|
// 24小时后过期
|
||||||
|
redPacket.setExpireTime(LocalDateTime.now().plusDays(1));
|
||||||
|
redPacket.setRemark(request.getRemark() != null && !request.getRemark().isEmpty()
|
||||||
|
? request.getRemark()
|
||||||
|
: "恭喜发财,大吉大利!");
|
||||||
|
return redPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扣减发送者余额并记录变动
|
||||||
|
*/
|
||||||
|
private void deductSenderBalance(Long senderId, RedPacket redPacket, BigDecimal beforeBalance) {
|
||||||
|
// 计算扣减后的余额
|
||||||
|
BigDecimal afterBalance = beforeBalance.subtract(redPacket.getTotalAmount());
|
||||||
|
umsAccountMapper.updateMoneyBalance(senderId, afterBalance);
|
||||||
|
|
||||||
|
// 记录金额变动
|
||||||
|
MemberAccountChangeRecord record = MemberAccountChangeRecord.builder()
|
||||||
|
.moneyBalance(beforeBalance)
|
||||||
|
.memberId(senderId)
|
||||||
|
.beforeBalance(beforeBalance)
|
||||||
|
.afterBalance(afterBalance)
|
||||||
|
.changeAmount(redPacket.getTotalAmount())
|
||||||
|
.changeType(CHANGE_TYPE_SEND)
|
||||||
|
.changeDesc("发送红包,红包ID:" + redPacket.getId())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
accountChangeRecordMapper.insert(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证红包状态
|
||||||
|
*/
|
||||||
|
private void validateRedPacketStatus(RedPacket redPacket, Long memberId) {
|
||||||
|
// 检查是否过期
|
||||||
|
if (redPacket.getExpireTime().isBefore(LocalDateTime.now())) {
|
||||||
|
if (redPacket.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
refundRemainingAmount(redPacket);
|
||||||
|
} else {
|
||||||
|
redPacket.setStatus(STATUS_EXPIRED);
|
||||||
|
redPacketMapper.updateById(redPacket);
|
||||||
|
throw new RuntimeException("红包已过期");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否已领完
|
||||||
|
if (redPacket.getStatus() == STATUS_ALL_RECEIVED) {
|
||||||
|
throw new RuntimeException("红包已被领完");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是自己发的红包
|
||||||
|
if (redPacket.getSenderId().equals(memberId)) {
|
||||||
|
throw new RuntimeException("不能领取自己发送的红包");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单聊红包只能指定接收者领取
|
||||||
|
if (redPacket.getChatType() == CHAT_TYPE_SINGLE &&
|
||||||
|
!redPacket.getReceiverId().equals(memberId)) {
|
||||||
|
throw new RuntimeException("您无权领取该红包");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款剩余金额
|
||||||
|
*/
|
||||||
|
private void refundRemainingAmount(RedPacket redPacket) {
|
||||||
|
Long senderId = redPacket.getSenderId();
|
||||||
|
BigDecimal remainingAmount = redPacket.getRemainingAmount();
|
||||||
|
|
||||||
|
// 查询当前余额
|
||||||
|
BigDecimal beforeBalance = umsAccountMapper.getMoneyBalanceByMemberId(senderId);
|
||||||
|
if (beforeBalance == null) {
|
||||||
|
throw new RuntimeException("发送者账户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增加余额
|
||||||
|
BigDecimal afterBalance = beforeBalance.add(remainingAmount);
|
||||||
|
umsAccountMapper.updateMoneyBalance(senderId, afterBalance);
|
||||||
|
|
||||||
|
// 记录金额变动
|
||||||
|
MemberAccountChangeRecord record = MemberAccountChangeRecord.builder()
|
||||||
|
.memberId(senderId)
|
||||||
|
.beforeBalance(beforeBalance)
|
||||||
|
.afterBalance(afterBalance)
|
||||||
|
.changeAmount(remainingAmount)
|
||||||
|
.changeType(CHANGE_TYPE_REFUND)
|
||||||
|
.changeDesc("红包退款,红包ID:" + redPacket.getId())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
accountChangeRecordMapper.insert(record);
|
||||||
|
|
||||||
|
// 更新红包状态为已退款
|
||||||
|
redPacket.setStatus(STATUS_REFUNDED);
|
||||||
|
redPacket.setRemainingAmount(BigDecimal.ZERO);
|
||||||
|
redPacketMapper.updateById(redPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算领取金额
|
||||||
|
*/
|
||||||
|
private BigDecimal calculateReceiveAmount(RedPacket redPacket) {
|
||||||
|
int remainingCount = redPacket.getRemainingCount();
|
||||||
|
BigDecimal remainingAmount = redPacket.getRemainingAmount();
|
||||||
|
|
||||||
|
if (remainingCount == 1) {
|
||||||
|
// 最后一个红包,领取全部剩余金额
|
||||||
|
return remainingAmount;
|
||||||
|
}
|
||||||
|
BigDecimal minAmount = new BigDecimal("0.01");
|
||||||
|
BigDecimal maxAmount = remainingAmount.subtract(new BigDecimal(remainingCount - 1).multiply(minAmount));
|
||||||
|
BigDecimal randomAmount = minAmount.add(new BigDecimal(Math.random() * maxAmount.doubleValue())).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||||
|
|
||||||
|
return randomAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新红包剩余金额和数量
|
||||||
|
*/
|
||||||
|
private void updateRedPacketRemaining(RedPacket redPacket, BigDecimal receiveAmount) {
|
||||||
|
redPacket.setRemainingAmount(redPacket.getRemainingAmount().subtract(receiveAmount));
|
||||||
|
redPacket.setRemainingCount(redPacket.getRemainingCount() - 1);
|
||||||
|
redPacketMapper.updateById(redPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建领取记录
|
||||||
|
*/
|
||||||
|
private RedPacketReceive createReceiveRecord(RedPacket redPacket, Long memberId, BigDecimal amount) {
|
||||||
|
RedPacketReceive record = new RedPacketReceive();
|
||||||
|
record.setPacketId(redPacket.getId());
|
||||||
|
record.setReceiverId(memberId);
|
||||||
|
record.setAmount(amount);
|
||||||
|
record.setReceviceTime(new DateTime());
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加领取者余额并记录变动
|
||||||
|
*/
|
||||||
|
private void addReceiverBalance(Long memberId, BigDecimal amount, Long packetId) {
|
||||||
|
// 查询当前余额
|
||||||
|
BigDecimal beforeBalance = umsAccountMapper.getMoneyBalanceByMemberId(memberId);
|
||||||
|
if (beforeBalance == null) {
|
||||||
|
throw new RuntimeException("领取者账户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 增加余额
|
||||||
|
BigDecimal afterBalance = beforeBalance.add(amount);
|
||||||
|
umsAccountMapper.updateMoneyBalance(memberId, afterBalance);
|
||||||
|
|
||||||
|
// 记录金额变动
|
||||||
|
MemberAccountChangeRecord record = MemberAccountChangeRecord.builder()
|
||||||
|
.memberId(memberId)
|
||||||
|
.beforeBalance(beforeBalance)
|
||||||
|
.afterBalance(afterBalance)
|
||||||
|
.changeAmount(amount)
|
||||||
|
.changeType(CHANGE_TYPE_RECEIVE)
|
||||||
|
.changeDesc("领取红包,红包ID:" + packetId)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
accountChangeRecordMapper.insert(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新红包状态
|
||||||
|
*/
|
||||||
|
private void updateRedPacketStatus(RedPacket redPacket) {
|
||||||
|
if (redPacket.getRemainingCount() == 0) {
|
||||||
|
redPacket.setStatus(STATUS_ALL_RECEIVED);
|
||||||
|
} else {
|
||||||
|
redPacket.setStatus(STATUS_PART_RECEIVED);
|
||||||
|
}
|
||||||
|
redPacketMapper.updateById(redPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时任务:检查并退款过期的红包
|
||||||
|
*/
|
||||||
|
@Scheduled(fixedRate = 1800000) // 每30分钟执行一次
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void checkAndRefundExpiredRedPackets() {
|
||||||
|
// 查询所有未领取或部分领取且已过期的红包
|
||||||
|
List<RedPacket> expiredRedPackets = redPacketMapper.selectExpiredRedPackets();
|
||||||
|
|
||||||
|
for (RedPacket redPacket : expiredRedPackets) {
|
||||||
|
if (redPacket.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
refundRemainingAmount(redPacket);
|
||||||
|
} else {
|
||||||
|
redPacket.setStatus(STATUS_EXPIRED);
|
||||||
|
redPacketMapper.updateById(redPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -46,13 +46,6 @@ public class SysTenantController extends BaseController {
|
|||||||
|
|
||||||
private final ISysTenantService tenantService;
|
private final ISysTenantService tenantService;
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 查询租户列表
|
|
||||||
// */
|
|
||||||
// @GetMapping("/all")
|
|
||||||
// public TableDataInfo<SysTenantVo> list(SysTenantBo bo, PageQuery pageQuery) {
|
|
||||||
// return tenantService.queryPageList(bo, pageQuery);
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Tag(name ="查询租户列表")
|
@Tag(name ="查询租户列表")
|
||||||
@SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
|
@SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
|
||||||
@ -76,15 +69,6 @@ public class SysTenantController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
|
|
||||||
// @SaCheckPermission("system:tenant:query")
|
|
||||||
// @GetMapping("/{id}")
|
|
||||||
// public R<SysTenantVo> getInfo(@NotNull(message = "主键不能为空")
|
|
||||||
// @PathVariable Long id) {
|
|
||||||
// return R.ok(tenantService.queryById(id));
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取租户详细信息
|
* 获取租户详细信息
|
||||||
*
|
*
|
||||||
@ -103,7 +87,6 @@ public class SysTenantController extends BaseController {
|
|||||||
/**
|
/**
|
||||||
* 新增租户
|
* 新增租户
|
||||||
*/
|
*/
|
||||||
// @ApiEncrypt
|
|
||||||
@SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
|
@SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
|
||||||
@SaCheckPermission("system:tenant:add")
|
@SaCheckPermission("system:tenant:add")
|
||||||
@Log(title = "租户管理", businessType = BusinessType.INSERT)
|
@Log(title = "租户管理", businessType = BusinessType.INSERT)
|
||||||
@ -147,13 +130,6 @@ public class SysTenantController extends BaseController {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @Log(title = "租户管理", businessType = BusinessType.DELETE)
|
|
||||||
// @DeleteMapping("/{id}")
|
|
||||||
// public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
|
||||||
// @PathVariable Long id) {
|
|
||||||
// return toAjax(tenantService.deleteWithValidByIds(List.of(ids), true));
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除租户
|
* 删除租户
|
||||||
|
@ -147,4 +147,7 @@ public class TenantDTO {
|
|||||||
|
|
||||||
@Schema(description = "邀请人名称")
|
@Schema(description = "邀请人名称")
|
||||||
private String inviteUserName;
|
private String inviteUserName;
|
||||||
|
|
||||||
|
@Schema(description = "分配比例模板名称")
|
||||||
|
private String templateName;
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
SELECT
|
SELECT
|
||||||
t.*,
|
t.*,
|
||||||
e.*,
|
e.*,
|
||||||
m.nickname AS inviteUserName
|
m.nickname AS inviteUserName,
|
||||||
|
ct.template_name AS templateName
|
||||||
FROM
|
FROM
|
||||||
sys_tenant t
|
sys_tenant t
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
sys_tenant_extend e ON t.tenant_id = e.tenant_id
|
sys_tenant_extend e ON t.tenant_id = e.tenant_id
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
ums_member m ON e.invite_user_id = m.id
|
ums_member m ON e.invite_user_id = m.id
|
||||||
|
LEFT JOIN
|
||||||
|
commission_template ct ON e.split_ratio = ct.id
|
||||||
<where>
|
<where>
|
||||||
<if test="query.tenantId != null and query.tenantId != ''">
|
<if test="query.tenantId != null and query.tenantId != ''">
|
||||||
AND t.tenant_id LIKE CONCAT('%', #{query.tenantId}, '%')
|
AND t.tenant_id LIKE CONCAT('%', #{query.tenantId}, '%')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user