补贴管理
This commit is contained in:
parent
3f099d8951
commit
50cbbb1311
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.bonus.canteen.core.account.constants;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public enum AccWalletClearTypeEnum {
|
||||||
|
CLEAR(1, "清空"),
|
||||||
|
CLEAR_BY(2, "清空至");
|
||||||
|
|
||||||
|
private final Integer key;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
private AccWalletClearTypeEnum(Integer key, String desc) {
|
||||||
|
this.key = key;
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
public Integer getKey() {
|
||||||
|
return this.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return this.desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.bonus.canteen.core.account.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.bonus.canteen.core.account.domain.AccInfo;
|
||||||
|
import com.bonus.canteen.core.account.domain.param.AccOperationQueryParam;
|
||||||
|
import com.bonus.canteen.core.account.domain.param.AccSubsidyParam;
|
||||||
|
import com.bonus.canteen.core.account.domain.param.AccountEnableDisableParam;
|
||||||
|
import com.bonus.canteen.core.account.domain.param.AccountInfoQueryParam;
|
||||||
|
import com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO;
|
||||||
|
import com.bonus.canteen.core.account.service.AccOperationHistoryService;
|
||||||
|
import com.bonus.canteen.core.account.service.AccSubService;
|
||||||
|
import com.bonus.canteen.core.account.service.IAccInfoService;
|
||||||
|
import com.bonus.common.core.utils.poi.ExcelUtil;
|
||||||
|
import com.bonus.common.core.web.controller.BaseController;
|
||||||
|
import com.bonus.common.core.web.domain.AjaxResult;
|
||||||
|
import com.bonus.common.core.web.page.TableDataInfo;
|
||||||
|
import com.bonus.common.houqin.constant.RetCodeEnum;
|
||||||
|
import com.bonus.common.houqin.i18n.I18n;
|
||||||
|
import com.bonus.common.log.annotation.SysLog;
|
||||||
|
import com.bonus.common.log.enums.OperaType;
|
||||||
|
import com.bonus.system.api.domain.SysUser;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账户资料Controller
|
||||||
|
*
|
||||||
|
* @author xsheng
|
||||||
|
* @date 2025-04-05
|
||||||
|
*/
|
||||||
|
@Api(tags = "账户补贴接口")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/acc/subsidy")
|
||||||
|
public class AccSubsidyController extends BaseController {
|
||||||
|
@Autowired
|
||||||
|
private AccSubService accSubService;
|
||||||
|
@ApiOperation("单人补贴")
|
||||||
|
@PostMapping("/add")
|
||||||
|
public AjaxResult individualAccSubsidyAdd(@RequestBody @Valid AccSubsidyParam param) {
|
||||||
|
this.accSubService.individualAccSubsidyAdd(param);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("补贴清空")
|
||||||
|
@PostMapping({"/clear"})
|
||||||
|
public AjaxResult individualAccSubsidyClear(@RequestBody @Valid AccSubsidyParam param) {
|
||||||
|
this.accSubService.individualAccSubsidyClear(param);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("单人补贴")
|
||||||
|
@PostMapping("/batch/add")
|
||||||
|
public AjaxResult batchAccSubsidyAdd(@RequestBody @Valid AccSubsidyParam param) {
|
||||||
|
this.accSubService.batchAccSubsidyAdd(param);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
@ApiOperation("补贴清空")
|
||||||
|
@PostMapping({"/batch/clear"})
|
||||||
|
public AjaxResult batchAccSubsidyClear(@RequestBody @Valid AccSubsidyParam param) {
|
||||||
|
this.accSubService.batchAccSubsidyClear(param);
|
||||||
|
return AjaxResult.success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,20 +19,20 @@ public class AccInfoVo {
|
||||||
@ApiModelProperty("账户状态 1正常 2冻结 3销户 4过期")
|
@ApiModelProperty("账户状态 1正常 2冻结 3销户 4过期")
|
||||||
private Integer accStatus;
|
private Integer accStatus;
|
||||||
@ApiModelProperty("账户可用总余额(不包括冻结金额)")
|
@ApiModelProperty("账户可用总余额(不包括冻结金额)")
|
||||||
private Long accBalTotal;
|
private BigDecimal accBalTotal;
|
||||||
@ApiModelProperty("账户总余额(包含冻结金额)")
|
@ApiModelProperty("账户总余额(包含冻结金额)")
|
||||||
private Long accAllBal;
|
private BigDecimal accAllBal;
|
||||||
@ApiModelProperty("个人钱包(可用)余额/分")
|
@ApiModelProperty("个人钱包(可用)余额/分")
|
||||||
private Long walletBal;
|
private BigDecimal walletBal;
|
||||||
@ApiModelProperty("补贴钱包(可用)余额/分")
|
@ApiModelProperty("补贴钱包(可用)余额/分")
|
||||||
private Long subsidyBal;
|
private BigDecimal subsidyBal;
|
||||||
@ApiModelProperty("红包余额")
|
@ApiModelProperty("红包余额")
|
||||||
private Long redEnvelope;
|
private BigDecimal redEnvelope;
|
||||||
@ApiModelProperty("个人钱包冻结金额")
|
@ApiModelProperty("个人钱包冻结金额")
|
||||||
private Long walletFreezeBal;
|
private BigDecimal walletFreezeBal;
|
||||||
@ApiModelProperty("补贴钱包冻结金额")
|
@ApiModelProperty("补贴钱包冻结金额")
|
||||||
private Long subFreezeBal;
|
private BigDecimal subFreezeBal;
|
||||||
private Long accFreezeBalTotal;
|
private BigDecimal accFreezeBalTotal;
|
||||||
private List<AccWalletInfo> walletInfoList;
|
private List<AccWalletInfo> walletInfoList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.bonus.canteen.core.account.domain;
|
package com.bonus.canteen.core.account.domain;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.bonus.common.core.annotation.Excel;
|
import com.bonus.common.core.annotation.Excel;
|
||||||
|
|
@ -35,17 +36,17 @@ public class AccWalletInfo extends BaseEntity {
|
||||||
/** 钱包余额/分 */
|
/** 钱包余额/分 */
|
||||||
@Excel(name = "钱包余额/分")
|
@Excel(name = "钱包余额/分")
|
||||||
@ApiModelProperty(value = "钱包余额/分")
|
@ApiModelProperty(value = "钱包余额/分")
|
||||||
private Long walletBal;
|
private BigDecimal walletBal;
|
||||||
|
|
||||||
/** 最低余额限制/分 */
|
/** 最低余额限制/分 */
|
||||||
@Excel(name = "最低余额限制/分")
|
@Excel(name = "最低余额限制/分")
|
||||||
@ApiModelProperty(value = "最低余额限制/分")
|
@ApiModelProperty(value = "最低余额限制/分")
|
||||||
private Long limitBalance;
|
private BigDecimal limitBalance;
|
||||||
|
|
||||||
/** 冻结金额 */
|
/** 冻结金额 */
|
||||||
@Excel(name = "冻结金额")
|
@Excel(name = "冻结金额")
|
||||||
@ApiModelProperty(value = "冻结金额")
|
@ApiModelProperty(value = "冻结金额")
|
||||||
private Long frozenBalance;
|
private BigDecimal frozenBalance;
|
||||||
|
|
||||||
/** 过期时间 */
|
/** 过期时间 */
|
||||||
@ApiModelProperty(value = "过期时间")
|
@ApiModelProperty(value = "过期时间")
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,21 @@ import java.math.BigDecimal;
|
||||||
@Data
|
@Data
|
||||||
public class WalletBalanceVO {
|
public class WalletBalanceVO {
|
||||||
@ApiModelProperty("个人钱包余额/分")
|
@ApiModelProperty("个人钱包余额/分")
|
||||||
private Long walletBal;
|
private BigDecimal walletBal;
|
||||||
@ApiModelProperty("补贴钱包余额/分")
|
@ApiModelProperty("补贴钱包余额/分")
|
||||||
private Long subsidyBal;
|
private BigDecimal subsidyBal;
|
||||||
@ApiModelProperty("红包余额")
|
@ApiModelProperty("红包余额")
|
||||||
private Long redEnvelope;
|
private BigDecimal redEnvelope;
|
||||||
@ApiModelProperty("个人钱包冻结金额")
|
@ApiModelProperty("个人钱包冻结金额")
|
||||||
private Long walletFreezeBal;
|
private BigDecimal walletFreezeBal;
|
||||||
@ApiModelProperty("补贴钱包冻结金额")
|
@ApiModelProperty("补贴钱包冻结金额")
|
||||||
private Long subFreezeBal;
|
private BigDecimal subFreezeBal;
|
||||||
@ApiModelProperty("冻结金额")
|
@ApiModelProperty("冻结金额")
|
||||||
private Long accFreezeBalTotal;
|
private BigDecimal accFreezeBalTotal;
|
||||||
@ApiModelProperty("账户总余额(包含冻结金额)")
|
@ApiModelProperty("账户总余额(包含冻结金额)")
|
||||||
private Long accAllBal;
|
private BigDecimal accAllBal;
|
||||||
@ApiModelProperty("账户可用余额总余额(不包括冻结金额)")
|
@ApiModelProperty("账户可用余额总余额(不包括冻结金额)")
|
||||||
private Long accBalTotal;
|
private BigDecimal accBalTotal;
|
||||||
@ApiModelProperty("账户状态 1正常 2冻结 3销户 4过期")
|
@ApiModelProperty("账户状态 1正常 2冻结 3销户 4过期")
|
||||||
private Integer accStatus;
|
private Integer accStatus;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.bonus.canteen.core.account.domain.param;
|
||||||
|
|
||||||
|
import com.bonus.common.core.web.domain.BaseEntity;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Max;
|
||||||
|
import javax.validation.constraints.Min;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
@Data
|
||||||
|
public class AccSubsidyParam extends BaseEntity {
|
||||||
|
@ApiModelProperty(
|
||||||
|
value = "用户编号",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
private @NotNull(
|
||||||
|
message = "用户编号不能为空"
|
||||||
|
) Long userId;
|
||||||
|
@ApiModelProperty(
|
||||||
|
value = "用户编号",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
private @NotNull(
|
||||||
|
message = "用户编号不能为空"
|
||||||
|
) List<Long> userIds;
|
||||||
|
@ApiModelProperty(
|
||||||
|
value = "充值金额/分",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
private @NotNull(
|
||||||
|
message = "金额不能为空"
|
||||||
|
) @Max(
|
||||||
|
value = 10000000L,
|
||||||
|
message = "超过最大金额限制"
|
||||||
|
) @Min(
|
||||||
|
value = 1L,
|
||||||
|
message = "小于最小充值金额"
|
||||||
|
) BigDecimal amount;
|
||||||
|
@ApiModelProperty("清空类型 清空-1 清空至-2")
|
||||||
|
private Integer clearType = 1;
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,8 @@ import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class AccountInfoQueryParam extends BaseEntity {
|
public class AccountInfoQueryParam extends BaseEntity {
|
||||||
|
@ApiModelProperty("用户编号集合")
|
||||||
|
private List<Long> userIds;
|
||||||
@ApiModelProperty("账户状态 1正常 2停用")
|
@ApiModelProperty("账户状态 1正常 2停用")
|
||||||
private List<Integer> accStatusList;
|
private List<Integer> accStatusList;
|
||||||
@ApiModelProperty("筛选钱包类型 0-账户总余额 1-个人钱包 2-补贴钱包")
|
@ApiModelProperty("筛选钱包类型 0-账户总余额 1-个人钱包 2-补贴钱包")
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ public class AccInfoDetailsVO {
|
||||||
private Integer userType;
|
private Integer userType;
|
||||||
@ApiModelProperty("用户部门")
|
@ApiModelProperty("用户部门")
|
||||||
private String deptName;
|
private String deptName;
|
||||||
|
@ApiModelProperty("用户部门")
|
||||||
|
private Long deptId;
|
||||||
@ApiModelProperty("用户类别(展示)")
|
@ApiModelProperty("用户类别(展示)")
|
||||||
@Excel(name = "用户类别(展示)")
|
@Excel(name = "用户类别(展示)")
|
||||||
private String userTypeName;
|
private String userTypeName;
|
||||||
|
|
@ -43,9 +45,6 @@ public class AccInfoDetailsVO {
|
||||||
@ApiModelProperty("补贴钱包余额/分")
|
@ApiModelProperty("补贴钱包余额/分")
|
||||||
@Excel(name = "补贴钱包余额/分")
|
@Excel(name = "补贴钱包余额/分")
|
||||||
private BigDecimal subsidyBal;
|
private BigDecimal subsidyBal;
|
||||||
@ApiModelProperty("红包余额")
|
|
||||||
@Excel(name = "红包余额")
|
|
||||||
private BigDecimal redEnvelope;
|
|
||||||
@ApiModelProperty("冻结金额")
|
@ApiModelProperty("冻结金额")
|
||||||
@Excel(name = "冻结金额")
|
@Excel(name = "冻结金额")
|
||||||
private BigDecimal accFreezeBalTotal;
|
private BigDecimal accFreezeBalTotal;
|
||||||
|
|
@ -55,7 +54,7 @@ public class AccInfoDetailsVO {
|
||||||
@ApiModelProperty("补贴钱包允许最低余额限制")
|
@ApiModelProperty("补贴钱包允许最低余额限制")
|
||||||
@Excel(name = "补贴钱包允许最低余额限制")
|
@Excel(name = "补贴钱包允许最低余额限制")
|
||||||
private BigDecimal minSubBalLimit;
|
private BigDecimal minSubBalLimit;
|
||||||
@ApiModelProperty("账户状态 1正常 2冻结 3销户 4过期")
|
@ApiModelProperty("账户状态 1正常 2冻结")
|
||||||
private Integer accStatus;
|
private Integer accStatus;
|
||||||
@ApiModelProperty("账户状态名称")
|
@ApiModelProperty("账户状态名称")
|
||||||
@Excel(name = "账户状态名称")
|
@Excel(name = "账户状态名称")
|
||||||
|
|
|
||||||
|
|
@ -76,4 +76,7 @@ public interface AccInfoMapper extends BaseMapper<AccInfo> {
|
||||||
AccInfoDetailsVO queryAccInfoBalanceSum(@Param("accountInfoQueryParam") AccountInfoQueryParam accountInfoQueryParam);
|
AccInfoDetailsVO queryAccInfoBalanceSum(@Param("accountInfoQueryParam") AccountInfoQueryParam accountInfoQueryParam);
|
||||||
|
|
||||||
void updateAccInfoEndDateByUserId(LocalDate endDate, List<Long> userIds, String updateBy);
|
void updateAccInfoEndDateByUserId(LocalDate endDate, List<Long> userIds, String updateBy);
|
||||||
|
List<AccInfoDetailsVO> queryAccInfoByUserIds(@Param("userIds") List<Long> userIds);
|
||||||
|
AccInfoDetailsVO queryAccInfoByUserId(@Param("userId") Long userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ public interface AccWalletInfoMapper {
|
||||||
* @return 钱包详情信息
|
* @return 钱包详情信息
|
||||||
*/
|
*/
|
||||||
public AccWalletInfo selectAccWalletInfoByUserId(Long userId);
|
public AccWalletInfo selectAccWalletInfoByUserId(Long userId);
|
||||||
|
public AccWalletInfo selectAccWalletInfoByUserIdAndWalletId(Long userId, Integer walletId);
|
||||||
|
|
||||||
List<AccWalletInfoVO> selectAccWalletInfoByUserIds(@Param("userIds") List<Long> userIds);
|
List<AccWalletInfoVO> selectAccWalletInfoByUserIds(@Param("userIds") List<Long> userIds);
|
||||||
|
|
||||||
|
|
@ -72,4 +73,12 @@ public interface AccWalletInfoMapper {
|
||||||
@Param("updateBy") String updateBy,
|
@Param("updateBy") String updateBy,
|
||||||
@Param("updateTime") LocalDate updateTime);
|
@Param("updateTime") LocalDate updateTime);
|
||||||
|
|
||||||
|
void addAccWalletInfo(@Param("amount") BigDecimal amount,
|
||||||
|
@Param("userId") Long userId,
|
||||||
|
@Param("walletId") Integer walletId
|
||||||
|
);
|
||||||
|
void reduceAccWalletInfo(@Param("amount") BigDecimal amount,
|
||||||
|
@Param("userId") Long userId,
|
||||||
|
@Param("walletId") Integer walletId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.bonus.canteen.core.account.service;
|
||||||
|
|
||||||
|
import com.bonus.canteen.core.account.domain.param.AccSubsidyParam;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface AccSubService {
|
||||||
|
void individualAccSubsidyAdd(AccSubsidyParam param);
|
||||||
|
|
||||||
|
void individualAccSubsidyClear(AccSubsidyParam param);
|
||||||
|
|
||||||
|
void batchAccSubsidyAdd(AccSubsidyParam param);
|
||||||
|
|
||||||
|
void batchAccSubsidyClear(AccSubsidyParam param);
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ import com.bonus.canteen.core.account.domain.param.AccountInfoQueryParam;
|
||||||
import com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO;
|
import com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO;
|
||||||
import com.bonus.canteen.core.account.domain.vo.AccInfoInvalidSumVO;
|
import com.bonus.canteen.core.account.domain.vo.AccInfoInvalidSumVO;
|
||||||
import com.bonus.system.api.domain.SysUser;
|
import com.bonus.system.api.domain.SysUser;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 账户资料Service接口
|
* 账户资料Service接口
|
||||||
|
|
@ -70,4 +71,7 @@ public interface IAccInfoService {
|
||||||
public String getOrderQRCode();
|
public String getOrderQRCode();
|
||||||
|
|
||||||
public WalletBalanceVO queryWalletBalance(AccInfo accInfo);
|
public WalletBalanceVO queryWalletBalance(AccInfo accInfo);
|
||||||
|
List<AccInfoDetailsVO> queryAccInfoByUserIds(List<Long> userIds);
|
||||||
|
AccInfoDetailsVO queryAccInfoByUserId(Long userId);
|
||||||
|
void checkAccStatus(AccInfoDetailsVO accInfoVO);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import com.bonus.canteen.core.account.domain.AccWalletInfo;
|
import com.bonus.canteen.core.account.domain.AccWalletInfo;
|
||||||
import com.bonus.canteen.core.account.domain.vo.AccWalletInfoVO;
|
import com.bonus.canteen.core.account.domain.vo.AccWalletInfoVO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 钱包详情信息Service接口
|
* 钱包详情信息Service接口
|
||||||
|
|
@ -21,6 +22,7 @@ public interface IAccWalletInfoService {
|
||||||
* @return 钱包详情信息
|
* @return 钱包详情信息
|
||||||
*/
|
*/
|
||||||
public AccWalletInfo selectAccWalletInfoByUserId(Long userId);
|
public AccWalletInfo selectAccWalletInfoByUserId(Long userId);
|
||||||
|
public AccWalletInfo selectAccWalletInfoByUserIdAndWalletId(Long userId, Integer walletId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询钱包详情信息列表
|
* 查询钱包详情信息列表
|
||||||
|
|
@ -67,5 +69,6 @@ public interface IAccWalletInfoService {
|
||||||
Map<Long, List<AccWalletInfoVO>> selectAccWalletInfoByUserIds(List<Long> userIds);
|
Map<Long, List<AccWalletInfoVO>> selectAccWalletInfoByUserIds(List<Long> userIds);
|
||||||
|
|
||||||
void updateMinBalance(List<Long> userIds, Integer walletId, BigDecimal minBalance);
|
void updateMinBalance(List<Long> userIds, Integer walletId, BigDecimal minBalance);
|
||||||
|
void addAccWalletInfo(BigDecimal amount, Long userId, Integer walletId);
|
||||||
|
void reduceAccWalletInfo(BigDecimal amount, Long userId, Integer walletId);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ import java.util.stream.Collectors;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.collection.ListUtil;
|
import cn.hutool.core.collection.ListUtil;
|
||||||
import cn.hutool.core.util.NumberUtil;
|
import cn.hutool.core.util.*;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.bonus.canteen.core.account.constants.AccWalletIdEnum;
|
import com.bonus.canteen.core.account.constants.AccWalletIdEnum;
|
||||||
import com.bonus.canteen.core.account.constants.AccStatusEnum;
|
import com.bonus.canteen.core.account.constants.AccStatusEnum;
|
||||||
|
|
@ -57,7 +56,6 @@ import javax.annotation.Resource;
|
||||||
* @date 2025-04-05
|
* @date 2025-04-05
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
|
||||||
public class AccInfoServiceImpl implements IAccInfoService {
|
public class AccInfoServiceImpl implements IAccInfoService {
|
||||||
private static final Logger log = LoggerFactory.getLogger(AccInfoServiceImpl.class);
|
private static final Logger log = LoggerFactory.getLogger(AccInfoServiceImpl.class);
|
||||||
|
|
||||||
|
|
@ -94,6 +92,9 @@ public class AccInfoServiceImpl implements IAccInfoService {
|
||||||
@Override
|
@Override
|
||||||
public List<AccInfoDetailsVO> selectAccInfoList(AccountInfoQueryParam accountInfoQueryParam) {
|
public List<AccInfoDetailsVO> selectAccInfoList(AccountInfoQueryParam accountInfoQueryParam) {
|
||||||
String encryptedSearchValue = SM4EncryptUtils.sm4Encrypt(accountInfoQueryParam.getSearchValue());
|
String encryptedSearchValue = SM4EncryptUtils.sm4Encrypt(accountInfoQueryParam.getSearchValue());
|
||||||
|
if(CollUtil.isEmpty(accountInfoQueryParam.getAccStatusList())) {
|
||||||
|
accountInfoQueryParam.setAccStatusList(Arrays.asList(AccStatusEnum.NORMAL.getKey(), AccStatusEnum.DEACTIVATE.getKey()));
|
||||||
|
}
|
||||||
List<AccInfoDetailsVO> list = accInfoMapper.queryAccInfoDetails(accountInfoQueryParam, encryptedSearchValue);
|
List<AccInfoDetailsVO> list = accInfoMapper.queryAccInfoDetails(accountInfoQueryParam, encryptedSearchValue);
|
||||||
handleResult(list);
|
handleResult(list);
|
||||||
return list;
|
return list;
|
||||||
|
|
@ -292,6 +293,9 @@ public class AccInfoServiceImpl implements IAccInfoService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccInfoDetailsVO queryAccInfoBalanceSum(AccountInfoQueryParam accountInfoQueryParam) {
|
public AccInfoDetailsVO queryAccInfoBalanceSum(AccountInfoQueryParam accountInfoQueryParam) {
|
||||||
|
if(CollUtil.isEmpty(accountInfoQueryParam.getAccStatusList())) {
|
||||||
|
accountInfoQueryParam.setAccStatusList(Arrays.asList(AccStatusEnum.NORMAL.getKey(), AccStatusEnum.DEACTIVATE.getKey()));
|
||||||
|
}
|
||||||
return accInfoMapper.queryAccInfoBalanceSum(accountInfoQueryParam);
|
return accInfoMapper.queryAccInfoBalanceSum(accountInfoQueryParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,11 +330,36 @@ public class AccInfoServiceImpl implements IAccInfoService {
|
||||||
return walletBalanceVO;
|
return walletBalanceVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setAccInfoVODetailList(AccInfoVo accInfoVo, List<AccWalletInfo> walletInfoList) {
|
@Override
|
||||||
if (ObjectUtil.isNotEmpty(walletInfoList)) {
|
public List<AccInfoDetailsVO> queryAccInfoByUserIds(List<Long> userIds) {
|
||||||
accInfoVo.setWalletBal(walletInfoList.stream().filter(o -> o.getWalletId().intValue() == AccWalletIdEnum.WALLET.getKey()).mapToLong(AccWalletInfo::getWalletBal).sum());
|
return accInfoMapper.queryAccInfoByUserIds(userIds);
|
||||||
accInfoVo.setSubsidyBal(walletInfoList.stream().filter(o -> o.getWalletId().intValue() == AccWalletIdEnum.SUBSIDY.getKey()).mapToLong(AccWalletInfo::getWalletBal).sum());
|
}
|
||||||
accInfoVo.setAccAllBal(accInfoVo.getWalletBal() + accInfoVo.getSubsidyBal());
|
@Override
|
||||||
|
public AccInfoDetailsVO queryAccInfoByUserId(Long userId) {
|
||||||
|
return accInfoMapper.queryAccInfoByUserId(userId);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void checkAccStatus(AccInfoDetailsVO accInfoVO) {
|
||||||
|
if (ObjectUtil.isNull(accInfoVO)) {
|
||||||
|
throw new ServiceException("账户不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
AccStatusEnum statusEnum = AccStatusEnum.getEnum(accInfoVO.getAccStatus());
|
||||||
|
if (ObjectUtil.isNull(statusEnum)) {
|
||||||
|
throw new ServiceException("账户状态异常");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusEnum == AccStatusEnum.DEACTIVATE) {
|
||||||
|
throw new ServiceException("账户已停用");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void setAccInfoVODetailList(AccInfoVo accInfoVo, List<AccWalletInfo> walletInfoList) {
|
||||||
|
// if (ObjectUtil.isNotEmpty(walletInfoList)) {
|
||||||
|
// accInfoVo.setWalletBal(walletInfoList.stream().filter(o -> o.getWalletId().intValue() == AccWalletIdEnum.WALLET.getKey()).mapToLong(AccWalletInfo::getWalletBal).sum());
|
||||||
|
// accInfoVo.setSubsidyBal(walletInfoList.stream().filter(o -> o.getWalletId().intValue() == AccWalletIdEnum.SUBSIDY.getKey()).mapToLong(AccWalletInfo::getWalletBal).sum());
|
||||||
|
// accInfoVo.setAccAllBal(accInfoVo.getWalletBal() + accInfoVo.getSubsidyBal());
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,202 @@
|
||||||
|
package com.bonus.canteen.core.account.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.bonus.canteen.core.account.constants.AccWalletClearTypeEnum;
|
||||||
|
import com.bonus.canteen.core.account.constants.AccWalletIdEnum;
|
||||||
|
import com.bonus.canteen.core.account.domain.AccWalletInfo;
|
||||||
|
import com.bonus.canteen.core.account.domain.param.AccSubsidyParam;
|
||||||
|
import com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO;
|
||||||
|
import com.bonus.canteen.core.account.service.AccSubService;
|
||||||
|
import com.bonus.canteen.core.account.service.IAccInfoService;
|
||||||
|
import com.bonus.canteen.core.account.service.IAccWalletInfoService;
|
||||||
|
import com.bonus.canteen.core.account.utils.AccRedisUtils;
|
||||||
|
import com.bonus.common.core.exception.ServiceException;
|
||||||
|
import com.bonus.common.houqin.i18n.I18n;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AccSubServiceImpl implements AccSubService {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AccSubServiceImpl.class);
|
||||||
|
@Autowired
|
||||||
|
@Lazy
|
||||||
|
private IAccInfoService accInfoService;
|
||||||
|
@Autowired
|
||||||
|
@Lazy
|
||||||
|
private IAccWalletInfoService accWalletInfoService;
|
||||||
|
@Resource(
|
||||||
|
name = "smartCanteenTaskExecutor"
|
||||||
|
)
|
||||||
|
@Lazy
|
||||||
|
private AsyncTaskExecutor asyncTaskExecutor;
|
||||||
|
|
||||||
|
@Transactional(
|
||||||
|
rollbackFor = {Exception.class}
|
||||||
|
)
|
||||||
|
public void individualAccSubsidyAdd(AccSubsidyParam param) {
|
||||||
|
AccInfoDetailsVO accInfoVO = this.accInfoService.queryAccInfoByUserId(param.getUserId());
|
||||||
|
if(Objects.isNull(accInfoVO)) {
|
||||||
|
throw new ServiceException("账户不存在");
|
||||||
|
}
|
||||||
|
accInfoService.checkAccStatus(accInfoVO);
|
||||||
|
addAccWalletBalance(param.getAmount(), param.getUserId(), AccWalletIdEnum.SUBSIDY.getKey());
|
||||||
|
}
|
||||||
|
@Transactional(
|
||||||
|
rollbackFor = {Exception.class}
|
||||||
|
)
|
||||||
|
public void individualAccSubsidyClear(AccSubsidyParam param) {
|
||||||
|
AccInfoDetailsVO accInfoVO = this.accInfoService.queryAccInfoByUserId(param.getUserId());
|
||||||
|
if(Objects.isNull(accInfoVO)) {
|
||||||
|
throw new ServiceException("账户不存在");
|
||||||
|
}
|
||||||
|
accInfoService.checkAccStatus(accInfoVO);
|
||||||
|
this.clearAccSubsidyHandler(accInfoVO, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearAccSubsidyHandler(AccInfoDetailsVO accInfoVO, AccSubsidyParam param) {
|
||||||
|
AccWalletInfo walletInfo = accWalletInfoService.selectAccWalletInfoByUserIdAndWalletId(accInfoVO.getUserId(), AccWalletIdEnum.SUBSIDY.getKey());
|
||||||
|
if(Objects.isNull(walletInfo)) {
|
||||||
|
throw new ServiceException("补贴钱包不存在");
|
||||||
|
}
|
||||||
|
BigDecimal walletBal = walletInfo.getWalletBal();
|
||||||
|
if (walletBal.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
throw new ServiceException(I18n.getMessage("补贴钱包余额不足"));
|
||||||
|
} else {
|
||||||
|
BigDecimal clearAmount = this.calculateClearAmount(walletBal, param.getClearType(), param.getAmount());
|
||||||
|
if (clearAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
throw new ServiceException(I18n.getMessage("清空后补贴钱包余额小于等于0"));
|
||||||
|
} else {
|
||||||
|
reduceAccWalletBalance(clearAmount, param.getUserId(), AccWalletIdEnum.SUBSIDY.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal calculateClearAmount(BigDecimal walletBal, Integer clearType, BigDecimal amount) {
|
||||||
|
BigDecimal clearAmount;
|
||||||
|
if (AccWalletClearTypeEnum.CLEAR_BY.getKey().equals(clearType)) {
|
||||||
|
clearAmount = amount.compareTo(walletBal) >= 0 ? BigDecimal.ZERO : walletBal.subtract(amount);
|
||||||
|
} else {
|
||||||
|
clearAmount = amount.compareTo(walletBal) >= 0 ? walletBal : amount;
|
||||||
|
}
|
||||||
|
return clearAmount.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : clearAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void batchAccSubsidyClear(AccSubsidyParam param) {
|
||||||
|
log.info("批量清空补贴用户数量:{}", param.getUserIds().size());
|
||||||
|
if(CollUtil.isEmpty(param.getUserIds())) {
|
||||||
|
throw new ServiceException("批量清空补贴用户为空");
|
||||||
|
}
|
||||||
|
List<AccInfoDetailsVO> accInfoVOList = this.accInfoService.queryAccInfoByUserIds(param.getUserIds());
|
||||||
|
log.info("批量清空补贴根据用户编号查询到{}人", accInfoVOList.size());
|
||||||
|
if (CollUtil.isEmpty(accInfoVOList)) {
|
||||||
|
throw new ServiceException("批量清空补贴查询到的用户为空");
|
||||||
|
} else {
|
||||||
|
this.asyncTaskExecutor.execute(() -> {
|
||||||
|
this.batchAccSubsidyClearHandler(accInfoVOList, param.getAmount(), param.getClearType());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void batchAccSubsidyAdd(AccSubsidyParam param) {
|
||||||
|
log.info("批量补贴用户数量:{}", param.getUserIds().size());
|
||||||
|
if(CollUtil.isEmpty(param.getUserIds())) {
|
||||||
|
throw new ServiceException("批量补贴用户为空");
|
||||||
|
}
|
||||||
|
List<AccInfoDetailsVO> accInfoVOList = this.accInfoService.queryAccInfoByUserIds(param.getUserIds());
|
||||||
|
log.info("批量补贴根据用户编号查询到{}人", accInfoVOList.size());
|
||||||
|
if (CollUtil.isEmpty(accInfoVOList)) {
|
||||||
|
throw new ServiceException("批量补贴查询到的用户为空");
|
||||||
|
} else {
|
||||||
|
this.asyncTaskExecutor.execute(() -> {
|
||||||
|
this.batchAccSubsidyAddHandler(accInfoVOList, param.getAmount());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void batchAccSubsidyAddHandler(List<AccInfoDetailsVO> accInfoDetails, BigDecimal amount) {
|
||||||
|
log.info("批量补贴开始:{}", accInfoDetails.size());
|
||||||
|
AccRedisUtils.lockBatchUpdateAccWallet();
|
||||||
|
try {
|
||||||
|
accInfoDetails.forEach((accInfo) -> {
|
||||||
|
try {
|
||||||
|
AccInfoDetailsVO accInfoVO = this.accInfoService.queryAccInfoByUserId(accInfo.getUserId());
|
||||||
|
if(Objects.isNull(accInfoVO)) {
|
||||||
|
throw new ServiceException(accInfo.getNickName() + "的账户不存在");
|
||||||
|
}
|
||||||
|
accInfoService.checkAccStatus(accInfoVO);
|
||||||
|
addAccWalletBalance(amount, accInfo.getUserId(), AccWalletIdEnum.SUBSIDY.getKey());
|
||||||
|
} catch (Exception var10) {
|
||||||
|
log.error("批量补贴充值异常", var10);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("批量补贴系统异常", ex);
|
||||||
|
} finally {
|
||||||
|
AccRedisUtils.unlockBatchUpdateAccWallet();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("批量补贴结束");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void batchAccSubsidyClearHandler(List<AccInfoDetailsVO> accInfoDetails, BigDecimal amount, Integer clearType) {
|
||||||
|
log.info("批量清空补贴开始:{}", accInfoDetails.size());
|
||||||
|
AccRedisUtils.lockBatchUpdateAccWallet();
|
||||||
|
try {
|
||||||
|
accInfoDetails.forEach((accInfo) -> {
|
||||||
|
try {
|
||||||
|
AccInfoDetailsVO accInfoVO = this.accInfoService.queryAccInfoByUserId(accInfo.getUserId());
|
||||||
|
if(Objects.isNull(accInfoVO)) {
|
||||||
|
throw new ServiceException(accInfo.getNickName() + "的账户不存在");
|
||||||
|
}
|
||||||
|
accInfoService.checkAccStatus(accInfoVO);
|
||||||
|
AccSubsidyParam param = new AccSubsidyParam();
|
||||||
|
param.setAmount(amount);
|
||||||
|
param.setUserId(accInfo.getUserId());
|
||||||
|
param.setClearType(clearType);
|
||||||
|
clearAccSubsidyHandler(accInfoVO, param);
|
||||||
|
} catch (Exception var10) {
|
||||||
|
log.error("批量清空补贴充值异常", var10);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("批量清空补贴系统异常", ex);
|
||||||
|
} finally {
|
||||||
|
AccRedisUtils.unlockBatchUpdateAccWallet();
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("批量清空补贴结束");
|
||||||
|
}
|
||||||
|
public void addAccWalletBalance(BigDecimal amount, Long userId, Integer walletId) {
|
||||||
|
log.info("新增补贴入参: amount:{}, userId:{},walletId:{}", amount, userId, walletId);
|
||||||
|
AccRedisUtils.lockUpdateAccWalletBalance(userId);
|
||||||
|
try {
|
||||||
|
accWalletInfoService.addAccWalletInfo(amount, userId, walletId);
|
||||||
|
log.info("新增补贴结束");
|
||||||
|
} finally {
|
||||||
|
AccRedisUtils.unlockUpdateAccWalletBalance(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reduceAccWalletBalance(BigDecimal amount, Long userId, Integer walletId) {
|
||||||
|
log.info("清空补贴入参: amount:{}, userId:{},walletId:{}", amount, userId, walletId);
|
||||||
|
AccRedisUtils.lockUpdateAccWalletBalance(userId);
|
||||||
|
try {
|
||||||
|
accWalletInfoService.reduceAccWalletInfo(amount, userId, walletId);
|
||||||
|
log.info("清空补贴结束");
|
||||||
|
} finally {
|
||||||
|
AccRedisUtils.unlockUpdateAccWalletBalance(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,11 @@ public class AccWalletInfoServiceImpl implements IAccWalletInfoService {
|
||||||
return accWalletInfoMapper.selectAccWalletInfoByUserId(userId);
|
return accWalletInfoMapper.selectAccWalletInfoByUserId(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccWalletInfo selectAccWalletInfoByUserIdAndWalletId(Long userId, Integer walletId) {
|
||||||
|
return accWalletInfoMapper.selectAccWalletInfoByUserIdAndWalletId(userId, walletId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询钱包详情信息列表
|
* 查询钱包详情信息列表
|
||||||
*
|
*
|
||||||
|
|
@ -146,5 +151,13 @@ public class AccWalletInfoServiceImpl implements IAccWalletInfoService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addAccWalletInfo(BigDecimal amount, Long userId, Integer walletId) {
|
||||||
|
accWalletInfoMapper.addAccWalletInfo(amount, userId, walletId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reduceAccWalletInfo(BigDecimal amount, Long userId, Integer walletId) {
|
||||||
|
accWalletInfoMapper.reduceAccWalletInfo(amount, userId, walletId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.bonus.canteen.core.account.utils;
|
||||||
|
|
||||||
|
import com.bonus.canteen.core.common.utils.RedisUtil;
|
||||||
|
import com.bonus.canteen.core.common.utils.TenantContextHolder;
|
||||||
|
import com.bonus.common.core.exception.ServiceException;
|
||||||
|
import com.bonus.common.houqin.constant.GlobalConstants;
|
||||||
|
import com.bonus.common.houqin.constant.LeConstants;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class AccRedisUtils {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(AccRedisUtils.class);
|
||||||
|
|
||||||
|
public static void lockUpdateAccWalletBalance(Long userId) {
|
||||||
|
String lockerKey = generateWalletLockerKey(userId);
|
||||||
|
if (!RedisUtil.tryLock(lockerKey, 10, 15)) {
|
||||||
|
throw new ServiceException("账户有交易正在进行中");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unlockUpdateAccWalletBalance(Long userId) {
|
||||||
|
String lockerKey = generateWalletLockerKey(userId);
|
||||||
|
try {
|
||||||
|
RedisUtil.safeUnLock(lockerKey);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("账户操作解锁异常", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void lockBatchUpdateAccWallet() {
|
||||||
|
String lockerKey = generateBatchUpdateAccWalletKey();
|
||||||
|
if (!RedisUtil.setNx(lockerKey, 1, 3600)) {
|
||||||
|
throw new ServiceException("已有任务在执行,请稍后~");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unlockBatchUpdateAccWallet() {
|
||||||
|
RedisUtil.delete(generateBatchUpdateAccWalletKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateWalletLockerKey(Long userId) {
|
||||||
|
return String.format("sc:acc_lock_merchant_%s_user_%s_wallet_update",
|
||||||
|
GlobalConstants.TENANT_ID, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateBatchUpdateAccWalletKey() {
|
||||||
|
return String.format("sc:acc_lock_merchant_%s_wallet_batch_update",
|
||||||
|
GlobalConstants.TENANT_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
package com.bonus.canteen.core.common.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import com.bonus.common.core.exception.ServiceException;
|
||||||
|
import com.bonus.common.houqin.utils.SpringContextHolder;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.ZSetOperations;
|
||||||
|
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
|
||||||
|
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class RedisUtil {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RedisUtil.class);
|
||||||
|
|
||||||
|
public static void setString(String key, String value) {
|
||||||
|
setString(key, value, (Long)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setString(String key, String value, Long timeOut) {
|
||||||
|
timeOut = timeoutFilter(timeOut);
|
||||||
|
if (value != null) {
|
||||||
|
if (timeOut != null) {
|
||||||
|
stringRedisTemplate().opsForValue().set(key, value, timeOut, TimeUnit.SECONDS);
|
||||||
|
} else {
|
||||||
|
stringRedisTemplate().opsForValue().set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean setIfPresentString(String key, String value, Long timeOut) {
|
||||||
|
timeOut = timeoutFilter(timeOut);
|
||||||
|
if (value != null) {
|
||||||
|
return timeOut != null ? stringRedisTemplate().opsForValue().setIfPresent(key, value, timeOut, TimeUnit.SECONDS) : stringRedisTemplate().opsForValue().setIfPresent(key, value);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setNx(String key, Object value, int expireTime) {
|
||||||
|
Boolean ifSucc = redisTemplate().opsForValue().setIfAbsent(key, value, (long)expireTime, TimeUnit.SECONDS);
|
||||||
|
return ifSucc == null ? false : ifSucc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(String key) {
|
||||||
|
return (String)stringRedisTemplate().opsForValue().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setObj(String key, Object value) {
|
||||||
|
setObj(key, value, (Long)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setObj(String key, Object value, Long timeOut) {
|
||||||
|
timeOut = timeoutFilter(timeOut);
|
||||||
|
if (value != null) {
|
||||||
|
if (timeOut != null) {
|
||||||
|
redisTemplate().opsForValue().set(key, value, timeOut, TimeUnit.SECONDS);
|
||||||
|
} else {
|
||||||
|
redisTemplate().opsForValue().set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getObj(String key) {
|
||||||
|
return redisTemplate().opsForValue().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(String key) {
|
||||||
|
redisTemplate().delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteByPattern(String keyPattern) {
|
||||||
|
Set<Object> keys = redisTemplate().keys(keyPattern);
|
||||||
|
if (CollUtil.isNotEmpty(keys)) {
|
||||||
|
redisTemplate().delete(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Long timeoutFilter(Long timeout) {
|
||||||
|
Long maxExpSecond = (Long)environment().getProperty("spring.redis.custom-max-expiration-second", Long.class);
|
||||||
|
if (maxExpSecond != null && (timeout == null || timeout > maxExpSecond)) {
|
||||||
|
timeout = maxExpSecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> keysByPattern(String pattern) {
|
||||||
|
Set<Object> keys = redisTemplate().keys(pattern);
|
||||||
|
return (List)(CollUtil.isEmpty(keys) ? new ArrayList() : (List)keys.stream().map(Object::toString).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void multiSet(Map map) {
|
||||||
|
redisTemplate().opsForValue().multiSet(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List multiGet(List keys) {
|
||||||
|
return redisTemplate().opsForValue().multiGet(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void zAdd(String key, Object value, double score) {
|
||||||
|
redisTemplate().opsForZSet().add(key, value, score);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Set<ZSetOperations.TypedTuple<Object>> zGetList(String key, long start, long end) {
|
||||||
|
return redisTemplate().opsForZSet().rangeWithScores(key, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StringRedisTemplate stringRedisTemplate() {
|
||||||
|
return (StringRedisTemplate) SpringContextHolder.getBean(StringRedisTemplate.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RedisTemplate<Object, Object> redisTemplate() {
|
||||||
|
return (RedisTemplate)SpringContextHolder.getBean("redisTemplate");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static Environment environment() {
|
||||||
|
return (Environment)SpringContextHolder.getBean(Environment.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer incr(String key, Long liveTime) {
|
||||||
|
return getRedisAtomicInteger(key, liveTime, true);
|
||||||
|
}
|
||||||
|
public static Integer getRedisAtomicInteger(String key, Long liveTime, Boolean incrDecrFlag) {
|
||||||
|
RedisConnectionFactory connectionFactory = redisTemplate().getConnectionFactory();
|
||||||
|
if (connectionFactory == null) {
|
||||||
|
throw new ServiceException("Redis连接异常");
|
||||||
|
} else {
|
||||||
|
RedisAtomicInteger entityIdCounter = new RedisAtomicInteger(key, connectionFactory);
|
||||||
|
if (incrDecrFlag == null) {
|
||||||
|
return entityIdCounter.get();
|
||||||
|
} else {
|
||||||
|
int increment;
|
||||||
|
if (incrDecrFlag) {
|
||||||
|
increment = entityIdCounter.getAndIncrement();
|
||||||
|
if (liveTime > 0L) {
|
||||||
|
entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return increment + 1;
|
||||||
|
} else {
|
||||||
|
increment = entityIdCounter.getAndDecrement();
|
||||||
|
if (liveTime > 0L) {
|
||||||
|
entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return increment - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RLock getLock(String key) {
|
||||||
|
return redissonClient().getLock(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RedissonClient redissonClient() {
|
||||||
|
return (RedissonClient)SpringContextHolder.getBean(RedissonClient.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public static boolean tryLock(String key) {
|
||||||
|
return tryLock(key, (Integer)null, (Integer)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
|
@Deprecated
|
||||||
|
public static boolean tryLock(String key, Integer waitSecond) {
|
||||||
|
return tryLock(key, waitSecond, (Integer)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
|
@Deprecated
|
||||||
|
public static boolean tryLock(String key, Integer waitSecond, Integer expireSecond) {
|
||||||
|
if (waitSecond == null && expireSecond != null) {
|
||||||
|
throw new ServiceException("不能这样使用");
|
||||||
|
} else {
|
||||||
|
RLock lock = redissonClient().getLock(key);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (waitSecond != null && expireSecond != null) {
|
||||||
|
return lock.tryLock((long)waitSecond, (long)expireSecond, TimeUnit.SECONDS);
|
||||||
|
} else {
|
||||||
|
return waitSecond != null ? lock.tryLock((long)waitSecond, TimeUnit.SECONDS) : lock.tryLock();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException var5) {
|
||||||
|
log.error("【分布式锁】tryLock失败:{}", var5.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Deprecated
|
||||||
|
public static void safeUnLock(String key) {
|
||||||
|
RLock lock = redissonClient().getLock(key);
|
||||||
|
if (lock.isHeldByCurrentThread() && lock.isLocked()) {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Long getIncr(RedisTemplate<Object, Object> redisTemplate, String key) {
|
||||||
|
RedisAtomicLong counter = new RedisAtomicLong(key, (RedisConnectionFactory) Objects.requireNonNull(redisTemplate.getConnectionFactory()));
|
||||||
|
long increment = counter.getAndIncrement();
|
||||||
|
if (increment <= 0L) {
|
||||||
|
setIncr(redisTemplate, key, 2);
|
||||||
|
return 1L;
|
||||||
|
} else {
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
LocalDateTime max = LocalDate.now().atTime(LocalTime.MAX);
|
||||||
|
long millis = Duration.between(now, max).toMillis();
|
||||||
|
counter.expire(millis, TimeUnit.MILLISECONDS);
|
||||||
|
return increment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIncr(RedisTemplate<Object, Object> redisTemplate, String key, int value) {
|
||||||
|
RedisAtomicLong counter = new RedisAtomicLong(key, (RedisConnectionFactory)Objects.requireNonNull(redisTemplate.getConnectionFactory()));
|
||||||
|
counter.set((long)value);
|
||||||
|
long millis = Duration.between(LocalDateTime.now(), LocalDate.now().atTime(LocalTime.MAX)).toMillis();
|
||||||
|
counter.expire(millis, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void lock(String key) {
|
||||||
|
RLock lock = redissonClient().getLock(key);
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -499,4 +499,35 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
#{userId}
|
#{userId}
|
||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<select id="queryAccInfoByUserIds" resultType="com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO">
|
||||||
|
SELECT ai.acc_id,
|
||||||
|
ai.user_id,
|
||||||
|
ai.end_date,
|
||||||
|
ai.acc_status,
|
||||||
|
su.nick_name,
|
||||||
|
su.phonenumber,
|
||||||
|
su.dept_id
|
||||||
|
FROM acc_info ai
|
||||||
|
LEFT JOIN sys_user su ON su.user_id = ai.user_id
|
||||||
|
LEFT JOIN sys_dept co ON co.dept_id = su.dept_id
|
||||||
|
WHERE ai.user_id in
|
||||||
|
<foreach collection="userIds" item="userId" separator="," open="(" close=")">
|
||||||
|
#{userId}
|
||||||
|
</foreach>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryAccInfoByUserId" resultType="com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO">
|
||||||
|
SELECT ai.acc_id,
|
||||||
|
ai.user_id,
|
||||||
|
ai.end_date,
|
||||||
|
ai.acc_status,
|
||||||
|
su.nick_name,
|
||||||
|
su.phonenumber,
|
||||||
|
su.dept_id
|
||||||
|
FROM acc_info ai
|
||||||
|
LEFT JOIN sys_user su ON su.user_id = ai.user_id
|
||||||
|
LEFT JOIN sys_dept co ON co.dept_id = su.dept_id
|
||||||
|
WHERE ai.user_id = #{userId}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -41,6 +41,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
where user_id = #{userId}
|
where user_id = #{userId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAccWalletInfoByUserIdAndWalletId" resultMap="AccWalletInfoResult">
|
||||||
|
<include refid="selectAccWalletInfoVo"/>
|
||||||
|
where user_id = #{userId} and wallet_id = #{walletId}
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectAccWalletInfoByUserIds" resultType="com.bonus.canteen.core.account.domain.vo.AccWalletInfoVO">
|
<select id="selectAccWalletInfoByUserIds" resultType="com.bonus.canteen.core.account.domain.vo.AccWalletInfoVO">
|
||||||
SELECT
|
SELECT
|
||||||
user_id,
|
user_id,
|
||||||
|
|
@ -149,4 +154,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
AND wallet_id = #{walletId}
|
AND wallet_id = #{walletId}
|
||||||
</where>
|
</where>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<update id="addAccWalletInfo">
|
||||||
|
UPDATE acc_wallet_info
|
||||||
|
SET wallet_bal = wallet_bal + #{amount}
|
||||||
|
WHERE user_id = #{userId}
|
||||||
|
AND wallet_id = #{walletId}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="reduceAccWalletInfo">
|
||||||
|
UPDATE acc_wallet_info
|
||||||
|
SET wallet_bal = wallet_bal - #{amount}
|
||||||
|
WHERE user_id = #{custId}
|
||||||
|
AND wallet_id = #{walletId}
|
||||||
|
</update>
|
||||||
</mapper>
|
</mapper>
|
||||||
Loading…
Reference in New Issue