Initial commit
This commit is contained in:
BIN
skins-promo/.DS_Store
vendored
Normal file
BIN
skins-promo/.DS_Store
vendored
Normal file
Binary file not shown.
40
skins-promo/pom.xml
Normal file
40
skins-promo/pom.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>4.8.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>skins-promo</artifactId>
|
||||
|
||||
<description>
|
||||
推广后台模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- 通用工具 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
</dependency>
|
||||
<!-- 框架核心 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi-framework</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>service-thirdparty</artifactId>
|
||||
<version>4.8.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>service-user</artifactId>
|
||||
<version>4.8.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.ruoyi.promo.contract.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GetPurchaseByUserIdRequest {
|
||||
/**
|
||||
* 玩家ID
|
||||
*/
|
||||
private Integer userId;
|
||||
|
||||
private String beginTime;
|
||||
|
||||
private String endTime;
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.ruoyi.promo.contract.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GetSubBranchesRequest {
|
||||
/**
|
||||
* 主播ID
|
||||
*/
|
||||
private Integer userId;
|
||||
/**
|
||||
* 玩家id
|
||||
*/
|
||||
private Integer playerId;
|
||||
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.ruoyi.promo.contract.request;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class QueryPromoteWelfareRequest {
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
private String beginTime;
|
||||
private String endTime;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.promo.contract.request;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RegisterRequest {
|
||||
@NotNull(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@NotNull(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
private String contactInformation;
|
||||
|
||||
@NotNull(message = "上级邀请码不能为空")
|
||||
private String parentInvitationCode;
|
||||
|
||||
private String code;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.promo.contract.request;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UpdateInvitationCodeRequest {
|
||||
@NotNull(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@NotNull(message = "邀请码不能为空")
|
||||
private String invitationCode;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.promo.contract.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class GetShareDomainResponse {
|
||||
private String zhuboShareDomain;
|
||||
private String zhaoshaoShareDomain;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ruoyi.promo.contract.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class GetSubBranchesResponse {
|
||||
private Integer total;
|
||||
|
||||
private List<UserInfo> rows;
|
||||
|
||||
@Data
|
||||
public static class UserInfo {
|
||||
private Integer userId;
|
||||
private String userName;
|
||||
private String nickName;
|
||||
//01主播 02普通用户
|
||||
private String userType;
|
||||
/**
|
||||
* 佣金比例
|
||||
*/
|
||||
private BigDecimal commissionRate;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
|
||||
private BigDecimal totalRecharge;
|
||||
private BigDecimal totalCost;
|
||||
private BigDecimal totalNormGameCost;
|
||||
private BigDecimal totalSpecialGameCost;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.ruoyi.promo.contract.response;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class QueryPromotionWelfareResponse {
|
||||
private Integer total;
|
||||
private List<Record> rows;
|
||||
private BigDecimal totalReward;
|
||||
|
||||
@Data
|
||||
public static class Record {
|
||||
private BigDecimal reward;
|
||||
private String date;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.promo.contract.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class DailyUserErcashVO {
|
||||
private String date;
|
||||
private BigDecimal dailyNormGameCost;
|
||||
private BigDecimal dailySpecialGameCost;
|
||||
private BigDecimal dailyRecharge;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.ruoyi.promo.controller;
|
||||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.annotation.UpdateUserCache;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.page.PageDataInfo;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.entity.TtRechargeProd;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.ApiLoginBody;
|
||||
import com.ruoyi.promo.contract.request.RegisterRequest;
|
||||
import com.ruoyi.promo.contract.request.UpdateInvitationCodeRequest;
|
||||
import com.ruoyi.promo.contract.response.GetShareDomainResponse;
|
||||
import com.ruoyi.promo.service.PromoLoginService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "推广后台用户认证")
|
||||
@RestController
|
||||
@RequestMapping("/promo")
|
||||
public class PromoLoginController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private PromoLoginService promoLoginService;
|
||||
|
||||
@ApiOperation("推广后台用户登录")
|
||||
@Anonymous
|
||||
@PostMapping("/login")
|
||||
public AjaxResult login(@RequestBody ApiLoginBody apiLoginBody) {
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
String token = promoLoginService.login(apiLoginBody.getUsername(), apiLoginBody.getPassword());
|
||||
ajax.put(Constants.TOKEN, token);
|
||||
ajax.put("user", null);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
@ApiOperation("推广后台用户注册")
|
||||
@Anonymous
|
||||
@PostMapping("/register")
|
||||
public AjaxResult register(@RequestBody RegisterRequest request) {
|
||||
R<TtUser> result = promoLoginService.register(request);
|
||||
if (R.isError(result)) {
|
||||
return AjaxResult.error(result.getMsg());
|
||||
}
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
String token = promoLoginService.login(request.getUsername(), request.getPassword());
|
||||
ajax.put(Constants.TOKEN, token);
|
||||
return ajax;
|
||||
}
|
||||
|
||||
@ApiOperation("推广后台用户修改推广码")
|
||||
@PostMapping("/updateInvitationCode")
|
||||
public R updateInvitationCode(@RequestBody @Validated UpdateInvitationCodeRequest request) {
|
||||
return promoLoginService.updateInvitationCode(request);
|
||||
}
|
||||
|
||||
@ApiOperation("获取主播/招商推广域名")
|
||||
@GetMapping("/getsharedomain")
|
||||
public R<GetShareDomainResponse> getShareDomain() {
|
||||
return promoLoginService.getShareDomain();
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("获取充值卡列表")
|
||||
@GetMapping("/card/list")
|
||||
public PageDataInfo<TtRechargeProd> cardList() {
|
||||
List<TtRechargeProd> list = promoLoginService.queryList();
|
||||
return getPageData(list);
|
||||
}
|
||||
|
||||
@ApiOperation("生成充值卡")
|
||||
@PostMapping("/generateCard/{rechargeListId}/{num}")
|
||||
@UpdateUserCache
|
||||
public R<List<String>> generateCard(@PathVariable("rechargeListId") Integer rechargeListId,
|
||||
@PathVariable("num") Integer num) {
|
||||
var loginUser = getLoginUser();
|
||||
if (loginUser == null || loginUser.getUserData() == null) {
|
||||
return R.fail("用户未登录");
|
||||
}
|
||||
if (!UserType.ANCHOR.getCode().equals(loginUser.getUserData().getUserType())) {
|
||||
return R.fail("无权限生成充值卡");
|
||||
}
|
||||
Long userId = getUserId();
|
||||
|
||||
List<String> cardList = promoLoginService.generateCard(userId.intValue(), rechargeListId, num);
|
||||
return R.ok(cardList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package com.ruoyi.promo.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.mapper.TtUserMapper;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.PageDataInfo;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.DateTimeUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.entity.TtCommissionRecord;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.vo.promotion.AnchorDailyTurnoverVo;
|
||||
import com.ruoyi.promo.contract.request.GetPurchaseByUserIdRequest;
|
||||
import com.ruoyi.promo.contract.request.GetSubBranchesRequest;
|
||||
import com.ruoyi.promo.contract.request.QueryPromoteWelfareRequest;
|
||||
import com.ruoyi.promo.contract.response.GetSubBranchesResponse;
|
||||
import com.ruoyi.promo.contract.response.QueryPromotionWelfareResponse;
|
||||
import com.ruoyi.promo.domain.dto.AnchorDayTurnoverDTO;
|
||||
import com.ruoyi.promo.domain.param.AnchorDayTurnoverParam;
|
||||
import com.ruoyi.promo.domain.vo.AnchorDayTurnoverVO;
|
||||
import com.ruoyi.promo.mapper.PromoTurnoverMapper;
|
||||
import com.ruoyi.promo.service.PromoTurnoverService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Api(tags = "推广流水")
|
||||
@RestController
|
||||
@RequestMapping("/promo/turnover")
|
||||
public class PromoTurnoverController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private PromoTurnoverService promoTurnoverService;
|
||||
|
||||
@Autowired
|
||||
private PromoTurnoverMapper promoTurnoverMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@Autowired
|
||||
private TtUserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper ttUserBlendErcashMapper;
|
||||
|
||||
@Anonymous
|
||||
@GetMapping("/test")
|
||||
public AjaxResult test(@RequestParam("uid")Long uid) {
|
||||
if (uid == null) {
|
||||
uid = getUserId();
|
||||
}
|
||||
userService.updateUserAccount(Math.toIntExact(uid), BigDecimal.valueOf(10), TtAccountRecordSource.P_WELFARE);
|
||||
return success();
|
||||
}
|
||||
|
||||
@ApiOperation("获取实时数据")
|
||||
@GetMapping("/getRealTimeData")
|
||||
public AjaxResult getRealTimeData() {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
return promoTurnoverService.getRealTimeData(userId.intValue());
|
||||
}
|
||||
|
||||
@ApiOperation("获取近10天推广数据")
|
||||
@GetMapping("getLast10DaysPromotionData")
|
||||
public AjaxResult getLast10DaysPromotionData() {
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
return promoTurnoverService.getLast10DaysPromotionData(userId.intValue());
|
||||
}
|
||||
|
||||
@ApiOperation("获取主播推广数据")
|
||||
@GetMapping("/getAnchorPromotionData")
|
||||
public TableDataInfo getAnchorPromotionData(AnchorDayTurnoverParam param) {
|
||||
if (param.getPageNum() == null || param.getPageNum() <= 0) {
|
||||
param.setPageNum(1);
|
||||
}
|
||||
if (param.getPageSize() == null || param.getPageSize() <= 0) {
|
||||
param.setPageSize(10);
|
||||
}
|
||||
|
||||
LocalDateTime beginTime = LocalDate.now().atStartOfDay();
|
||||
LocalDateTime endTime = LocalDate.now().plusDays(1).atStartOfDay();
|
||||
if (StringUtils.isNotEmpty(param.getBeginTime())) {
|
||||
beginTime = DateTimeUtils.toLocalDateTime(DateTimeUtils.dateTime(DateTimeUtils.YYYY_MM_DD, param.getBeginTime()));
|
||||
}
|
||||
if (StringUtils.isNotEmpty(param.getEndTime())) {
|
||||
endTime = DateTimeUtils.toLocalDateTime(DateTimeUtils.dateTime(DateTimeUtils.YYYY_MM_DD, param.getEndTime()));
|
||||
}
|
||||
|
||||
var loginUser = getLoginUser();
|
||||
if (loginUser == null || loginUser.getUserData() == null) {
|
||||
TableDataInfo pageDataInfo = new TableDataInfo();
|
||||
pageDataInfo.setTotal(0);
|
||||
pageDataInfo.setCode(HttpStatus.ERROR);
|
||||
pageDataInfo.setMsg("没登录");
|
||||
return pageDataInfo;
|
||||
}
|
||||
if (!UserType.BUSINESS_USER.getCode().equals(loginUser.getUserData().getUserType())) {
|
||||
TableDataInfo pageDataInfo = new TableDataInfo();
|
||||
pageDataInfo.setTotal(0);
|
||||
pageDataInfo.setCode(HttpStatus.ERROR);
|
||||
pageDataInfo.setMsg("不是招商");
|
||||
return pageDataInfo;
|
||||
}
|
||||
Long userId = getUserId();
|
||||
|
||||
|
||||
Page<TtUser> pageInfo = new Page<>(param.getPageNum(), param.getPageSize());
|
||||
pageInfo.setOptimizeCountSql(false);
|
||||
|
||||
var anchorPage = new LambdaQueryChainWrapper<>(userMapper).eq(TtUser::getParentId, userId)
|
||||
.eq(param.getParentId() != null, TtUser::getUserId, param.getParentId())
|
||||
.eq( StringUtils.isNotEmpty(param.getParentNickName()), TtUser::getNickName, param.getParentNickName()).page(pageInfo);
|
||||
var anchorList = anchorPage.getRecords();
|
||||
if (CollectionUtils.isEmpty(anchorList)) {
|
||||
TableDataInfo pageDataInfo = new TableDataInfo();
|
||||
pageDataInfo.setTotal(0);
|
||||
pageDataInfo.setCode(HttpStatus.SUCCESS);
|
||||
pageDataInfo.setMsg("成功");
|
||||
return pageDataInfo;
|
||||
}
|
||||
|
||||
LocalDateTime finalBeginTime = beginTime;
|
||||
LocalDateTime finalEndTime = endTime;
|
||||
var data = anchorList.stream().map(anchor -> {
|
||||
var normalUserList = new LambdaQueryChainWrapper<>(userMapper).eq(TtUser::getParentId, anchor.getUserId()).list();
|
||||
AnchorDayTurnoverVO item = new AnchorDayTurnoverVO();
|
||||
item.setUserId(anchor.getUserId());
|
||||
item.setNickName(anchor.getNickName());
|
||||
item.setTotalByParent(BigDecimal.ZERO);
|
||||
if (CollectionUtils.isEmpty(normalUserList)) {
|
||||
return item;
|
||||
}
|
||||
|
||||
var ids = normalUserList.stream().map(TtUser::getUserId).collect(Collectors.toList());
|
||||
var records = new LambdaQueryChainWrapper<>(ttUserBlendErcashMapper)
|
||||
.in(TtUserBlendErcash::getUserId, ids)
|
||||
.in(TtUserBlendErcash::getSource, TtAccountRecordSource.getGameConsumeCodes())
|
||||
.between(TtUserBlendErcash::getCreateTime, finalBeginTime, finalEndTime)
|
||||
.list();
|
||||
if (CollectionUtils.isNotEmpty(records)) {
|
||||
item.setTotalByParent(records.stream().map(TtUserBlendErcash::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).abs());
|
||||
}
|
||||
return item;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
TableDataInfo pageDataInfo = new TableDataInfo();
|
||||
pageDataInfo.setTotal(anchorPage.getTotal());
|
||||
pageDataInfo.setCode(HttpStatus.SUCCESS);
|
||||
pageDataInfo.setMsg("查询成功");
|
||||
pageDataInfo.setRows(data);
|
||||
return pageDataInfo;
|
||||
}
|
||||
|
||||
@ApiOperation("获取下级历史数据")
|
||||
@GetMapping("/getSubBranches")
|
||||
public AjaxResult getSubBranches(GetSubBranchesRequest request) {
|
||||
Long userId = getUserId();
|
||||
request.setUserId(userId.intValue());
|
||||
GetSubBranchesResponse response = promoTurnoverService.getSubBranches(request);
|
||||
return AjaxResult.success(response);
|
||||
}
|
||||
|
||||
@ApiOperation("获取日流水记录")
|
||||
@GetMapping("/getPurchaseByUserId/{userId}")
|
||||
public TableDataInfo getPurchaseByUserId(GetPurchaseByUserIdRequest request) {
|
||||
return promoTurnoverService.getPurchaseByUserId(request);
|
||||
}
|
||||
|
||||
@ApiOperation("获取佣金比例")
|
||||
@GetMapping("/getCommissionRateByUserId/{userId}")
|
||||
public AjaxResult getCommissionRateByUserId(@PathVariable("userId") Integer userId) {
|
||||
BigDecimal commissionRate = promoTurnoverService.getCommissionRateByUserId(userId);
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("commissionRate", commissionRate);
|
||||
return AjaxResult.success(map);
|
||||
}
|
||||
|
||||
@ApiOperation("获取佣金比例")
|
||||
@PutMapping("/updateCommissionRate")
|
||||
public AjaxResult updateCommissionRate(@RequestBody TtUser ttUser) {
|
||||
Integer userId = ttUser.getUserId();
|
||||
BigDecimal commissionRate = ttUser.getCommissionRate();
|
||||
if (Objects.isNull(userId)) {
|
||||
return AjaxResult.error("用户ID不能为空");
|
||||
}
|
||||
if (Objects.isNull(commissionRate)) {
|
||||
return AjaxResult.error("分佣比例不能为空");
|
||||
}
|
||||
if (commissionRate.compareTo(BigDecimal.valueOf(0.1)) > 0) {
|
||||
return AjaxResult.error("分佣比例不能超过0.1");
|
||||
}
|
||||
if (commissionRate.compareTo(BigDecimal.valueOf(0.01)) < 0) {
|
||||
return AjaxResult.error("分佣比例不能低于0.01");
|
||||
}
|
||||
int row = promoTurnoverService.updateCommissionRate(userId, commissionRate);
|
||||
return row >= 1 ? AjaxResult.success("修改成功") : AjaxResult.error("修改失败");
|
||||
}
|
||||
|
||||
@ApiOperation("获取佣金列表")
|
||||
@GetMapping("/getCommissionList")
|
||||
public AjaxResult getCommissionList() {
|
||||
Long userId = getUserId();
|
||||
List<TtCommissionRecord> commissionList = promoTurnoverService.getCommissionList(userId.intValue());
|
||||
return AjaxResult.success(commissionList);
|
||||
}
|
||||
|
||||
@ApiOperation("获取主播推广奖励列表")
|
||||
@GetMapping("/queryPromoteWelfare")
|
||||
public AjaxResult queryPromoteWelfare(QueryPromoteWelfareRequest request) {
|
||||
Long userId = getUserId();
|
||||
QueryPromotionWelfareResponse response = promoTurnoverService.queryPromoteWelfare(Math.toIntExact(userId), request);
|
||||
return AjaxResult.success(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.ruoyi.promo.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 主播日流水
|
||||
*/
|
||||
@Data
|
||||
public class AnchorDayTurnoverDTO {
|
||||
|
||||
/**
|
||||
* 本人ID
|
||||
*/
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
* 玩家上级ID
|
||||
*/
|
||||
private Integer parentId;
|
||||
|
||||
/**
|
||||
* 玩家上级昵称
|
||||
*/
|
||||
private String parentNickName;
|
||||
|
||||
/**
|
||||
* 名下所有玩家ID
|
||||
*/
|
||||
private List<Integer> userIds;
|
||||
|
||||
private List<Integer> sourceCodes;
|
||||
|
||||
private String beginTime;
|
||||
|
||||
private String endTime;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.promo.domain.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class TotalUserExpenditureDTO {
|
||||
private Integer userId;
|
||||
private String userName;
|
||||
private String userType;
|
||||
private Integer parentId;
|
||||
private BigDecimal commissionRate;
|
||||
private BigDecimal amount;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.ruoyi.promo.domain.param;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 主播日流水
|
||||
*/
|
||||
@Data
|
||||
public class AnchorDayTurnoverParam {
|
||||
|
||||
/**
|
||||
* 玩家上级ID
|
||||
*/
|
||||
private Integer parentId;
|
||||
|
||||
/**
|
||||
* 玩家上级昵称
|
||||
*/
|
||||
private String parentNickName;
|
||||
|
||||
private String beginTime;
|
||||
|
||||
private String endTime;
|
||||
|
||||
private Integer pageNum;
|
||||
private Integer pageSize;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.ruoyi.promo.domain.param;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class GetPlayersTurnoverParam {
|
||||
private List<Integer> userIds;
|
||||
private List<Integer> sourceCodes;
|
||||
private String beginTime;
|
||||
private String endTime;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.ruoyi.promo.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 主播日流水
|
||||
*/
|
||||
@Data
|
||||
public class AnchorDayTurnoverVO {
|
||||
|
||||
/**
|
||||
* 玩家ID
|
||||
*/
|
||||
private Integer userId;
|
||||
|
||||
/**
|
||||
* 上级ID
|
||||
*/
|
||||
private Integer parentId;
|
||||
|
||||
/**
|
||||
* 玩家昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 上级昵称
|
||||
*/
|
||||
private String parentNickName;
|
||||
|
||||
/**
|
||||
* 主播下级日消费
|
||||
*/
|
||||
private BigDecimal dailyTotal;
|
||||
|
||||
/**
|
||||
* 主播下级总消费
|
||||
*/
|
||||
private BigDecimal totalByParent;
|
||||
|
||||
/**
|
||||
* 主播下级日充值
|
||||
*/
|
||||
private BigDecimal dailyRechargeTotal;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date date;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.ruoyi.promo.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日邀请
|
||||
*/
|
||||
@Data
|
||||
public class DayInviteVO {
|
||||
private Date date;
|
||||
private Integer anchorCount;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.ruoyi.promo.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日流水
|
||||
*/
|
||||
@Data
|
||||
public class DayTurnoverVO {
|
||||
private Date date;
|
||||
private BigDecimal amount;
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.ruoyi.promo.mapper;
|
||||
|
||||
import com.ruoyi.domain.entity.TtCommissionRecord;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.promo.domain.dto.AnchorDayTurnoverDTO;
|
||||
import com.ruoyi.promo.domain.dto.TotalUserExpenditureDTO;
|
||||
import com.ruoyi.promo.domain.param.GetPlayersTurnoverParam;
|
||||
import com.ruoyi.promo.domain.vo.AnchorDayTurnoverVO;
|
||||
import com.ruoyi.promo.domain.vo.DayInviteVO;
|
||||
import com.ruoyi.promo.domain.vo.DayTurnoverVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 推广流水Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface PromoTurnoverMapper {
|
||||
|
||||
@Select("select SUM(amount) from tt_user_blend_ercash where user_id = #{userId} and source = #{source}")
|
||||
BigDecimal queryTotalRewardBySource(@Param("userId")Integer userId, @Param("source")Integer source);
|
||||
|
||||
@Select(
|
||||
"<script>" +
|
||||
"SELECT " +
|
||||
" DATE(create_time) as dateStr " +
|
||||
" FROM " +
|
||||
" tt_user_blend_ercash " +
|
||||
" WHERE " +
|
||||
" user_id = #{userId}" +
|
||||
" <if test=\"beginTime != null\">" +
|
||||
" AND create_time >= #{beginTime}" +
|
||||
" </if>\n" +
|
||||
" <if test=\"endTime != null\">" +
|
||||
" AND create_time <= #{endTime}" +
|
||||
" </if>" +
|
||||
" And (amount < 0 OR source = 1)" +
|
||||
" GROUP BY " +
|
||||
" DATE(create_time)" +
|
||||
" ORDER BY " +
|
||||
" DATE(create_time) DESC" +
|
||||
"</script>")
|
||||
List<String> queryPlayerErcash(@Param("userId") Integer userId,
|
||||
@Param("beginTime") String beginTime, @Param("endTime") String endTime);
|
||||
|
||||
@Select("select SUM(amount) from tt_user_blend_ercash where user_id = #{userId} and DATE(create_time) = #{date} and amount < 0")
|
||||
BigDecimal queryDailySum(@Param("userId")Integer userId, @Param("date")String date);
|
||||
|
||||
/**
|
||||
* 获取直属主播数量
|
||||
*/
|
||||
int getAnchorCount(Integer userId);
|
||||
|
||||
/**
|
||||
* 获取玩家流水
|
||||
*/
|
||||
BigDecimal getPlayersTurnover(GetPlayersTurnoverParam param);
|
||||
|
||||
/**
|
||||
* 获取名下主播近10天日流水
|
||||
*/
|
||||
List<DayTurnoverVO> getLast10DaysTurnover(@Param("userIds") List<Integer> userIds,
|
||||
@Param("sourceCodes") List<Integer> sourceCodes);
|
||||
|
||||
/**
|
||||
* 获取名下主播近10天日邀请
|
||||
*/
|
||||
List<DayInviteVO> getLast10DaysInvite(Integer userId);
|
||||
|
||||
/**
|
||||
* 查询名下主播每日流水
|
||||
*/
|
||||
List<AnchorDayTurnoverVO> getAnchorDayTurnover(AnchorDayTurnoverDTO anchorDayTurnoverDTO);
|
||||
|
||||
@Select("SELECT * FROM tt_user WHERE parent_id = #{parentId}")
|
||||
List<TtUser> findByParentId(@Param("parentId") int parentId);
|
||||
|
||||
@Select("SELECT * FROM tt_user WHERE user_id = #{userId}")
|
||||
TtUser findById(@Param("userId") int id);
|
||||
|
||||
/**
|
||||
* 获取消费记录
|
||||
*/
|
||||
List<TtUserBlendErcash> getPurchaseByUserId(Integer userId);
|
||||
|
||||
|
||||
@Select("select sum(total) from tt_user_blend_ercash where user_id = #{userId} and type=1 and source = 1 and create_time >= #{startDate} and create_time < #{endDate}")
|
||||
BigDecimal getDailyTotalRecharge(@Param("userId") Integer userId,
|
||||
@Param("startDate") Date startDate,
|
||||
@Param("endDate") Date endDate);
|
||||
|
||||
/**
|
||||
* 获取佣金比例
|
||||
*/
|
||||
BigDecimal getCommissionRateByUserId(Integer userId);
|
||||
|
||||
/**
|
||||
* 修改佣金比例
|
||||
*/
|
||||
int updateCommissionRate(@Param("userId") Integer userId, @Param("commissionRate") BigDecimal commissionRate);
|
||||
|
||||
/**
|
||||
* 获取佣金列表
|
||||
*/
|
||||
List<TtCommissionRecord> getCommissionList(Integer userId);
|
||||
|
||||
/**
|
||||
* 获取上个月用户消费额
|
||||
*/
|
||||
List<TotalUserExpenditureDTO> getLastMonthTotalUserExpenditure();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.ruoyi.promo.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.domain.entity.TtRechargeProd;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.promo.contract.request.RegisterRequest;
|
||||
import com.ruoyi.promo.contract.request.UpdateInvitationCodeRequest;
|
||||
import com.ruoyi.promo.contract.response.GetShareDomainResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PromoLoginService {
|
||||
|
||||
String login(String username, String password);
|
||||
R<TtUser> register(RegisterRequest request);
|
||||
|
||||
R<TtUser> updateInvitationCode(UpdateInvitationCodeRequest request);
|
||||
|
||||
R<GetShareDomainResponse> getShareDomain();
|
||||
|
||||
List<TtRechargeProd> queryList();
|
||||
|
||||
List<String> generateCard(Integer userId, Integer rechargeListId, Integer num);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.ruoyi.promo.service;
|
||||
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.domain.entity.TtCommissionRecord;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.promo.contract.request.GetPurchaseByUserIdRequest;
|
||||
import com.ruoyi.promo.contract.request.GetSubBranchesRequest;
|
||||
import com.ruoyi.promo.contract.request.QueryPromoteWelfareRequest;
|
||||
import com.ruoyi.promo.contract.response.GetSubBranchesResponse;
|
||||
import com.ruoyi.promo.contract.response.QueryPromotionWelfareResponse;
|
||||
import com.ruoyi.promo.domain.dto.AnchorDayTurnoverDTO;
|
||||
import com.ruoyi.promo.domain.vo.AnchorDayTurnoverVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
public interface PromoTurnoverService {
|
||||
|
||||
/**
|
||||
* 递归全部最下级玩家
|
||||
*/
|
||||
List<TtUser> recursionAllPlayer(Integer userId);
|
||||
|
||||
/**
|
||||
* 获取实时数据
|
||||
*/
|
||||
AjaxResult getRealTimeData(Integer userId);
|
||||
|
||||
/**
|
||||
* 获取近10天推广数据
|
||||
*/
|
||||
AjaxResult getLast10DaysPromotionData(Integer userId);
|
||||
|
||||
/**
|
||||
* 获取名下主播每日流水
|
||||
*/
|
||||
List<AnchorDayTurnoverVO> getAnchorDayTurnover(AnchorDayTurnoverDTO anchorDayTurnoverDTO);
|
||||
|
||||
/**
|
||||
* 获取下级分支
|
||||
*/
|
||||
GetSubBranchesResponse getSubBranches(GetSubBranchesRequest request);
|
||||
|
||||
/**
|
||||
* 获取日流水记录
|
||||
*/
|
||||
TableDataInfo getPurchaseByUserId(GetPurchaseByUserIdRequest userId);
|
||||
|
||||
/**
|
||||
* 获取佣金比例
|
||||
*/
|
||||
BigDecimal getCommissionRateByUserId(Integer userId);
|
||||
|
||||
/**
|
||||
* 修改佣金比例
|
||||
*/
|
||||
int updateCommissionRate(Integer userId, BigDecimal commissionRate);
|
||||
|
||||
/**
|
||||
* 获取佣金列表
|
||||
*/
|
||||
List<TtCommissionRecord> getCommissionList(Integer userId);
|
||||
|
||||
QueryPromotionWelfareResponse queryPromoteWelfare(Integer userId, QueryPromoteWelfareRequest request);
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
package com.ruoyi.promo.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.ruoyi.admin.mapper.TtRechargeCardMapper;
|
||||
import com.ruoyi.admin.mapper.TtRechargeProdMapper;
|
||||
import com.ruoyi.admin.mapper.TtRedPacketMapper;
|
||||
import com.ruoyi.admin.mapper.TtUserMapper;
|
||||
import com.ruoyi.admin.service.TtUserService;
|
||||
import com.ruoyi.admin.util.RandomUtils;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.ip.IpUtils;
|
||||
import com.ruoyi.common.utils.uuid.IdUtils;
|
||||
import com.ruoyi.common.utils.uuid.UUID;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.UserType;
|
||||
import com.ruoyi.domain.entity.TtRechargeProd;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.domain.other.TtRedPacket;
|
||||
import com.ruoyi.framework.web.service.SysLoginService;
|
||||
import com.ruoyi.framework.web.service.TokenService;
|
||||
import com.ruoyi.promo.contract.request.RegisterRequest;
|
||||
import com.ruoyi.promo.contract.request.UpdateInvitationCodeRequest;
|
||||
import com.ruoyi.promo.contract.response.GetShareDomainResponse;
|
||||
import com.ruoyi.promo.service.PromoLoginService;
|
||||
import com.ruoyi.system.domain.SysConfig;
|
||||
import com.ruoyi.system.mapper.SysConfigMapper;
|
||||
import com.ruoyi.thirdparty.common.service.ApiSmsService;
|
||||
import com.ruoyi.user.service.UserIdGenerator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PromoLoginServiceImpl implements PromoLoginService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private SysLoginService sysLoginService;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private TtUserMapper ttUserMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserService userService;
|
||||
|
||||
@Autowired
|
||||
private ApiSmsService apiSmsService;
|
||||
|
||||
@Autowired
|
||||
private UserIdGenerator userIdGenerator;
|
||||
|
||||
@Autowired
|
||||
private SysConfigMapper sysConfigMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRechargeCardMapper rechargeCardMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRechargeProdMapper rechargeListMapper;
|
||||
|
||||
@Autowired
|
||||
private TtRedPacketMapper redPacketMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public String login(String username, String password) {
|
||||
// 登录前置校验
|
||||
sysLoginService.loginPreCheck(username, password);
|
||||
// 将前缀提供给ApiUserDetailsServiceImpl.loadUserByUsername,只允许运营类型用户登录
|
||||
LoginUser loginUser = sysLoginService.createLoginUser("promo_" + username, password);
|
||||
// 记录登录信息
|
||||
recordLoginInfo(loginUser.getUserId());
|
||||
return tokenService.createToken(loginUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<TtUser> register(RegisterRequest request) {
|
||||
if (StringUtils.isEmpty(request.getUsername())) return R.fail("手机号不能为空");
|
||||
if (!Validator.isMobile(request.getUsername())) return R.fail("手机号格式错误,请检查手机号是否输入正确!");
|
||||
if (StringUtils.isEmpty(request.getPassword())) return R.fail("用户密码不能为空");
|
||||
if (StringUtils.isEmpty(request.getParentInvitationCode())) return R.fail("上级邀请码不能为空");
|
||||
if (!NumberUtil.isNumber(request.getCode()) || request.getCode().trim().length() != 4)
|
||||
return R.fail("验证码错误");
|
||||
|
||||
if (!userService.checkPhoneUnique(TtUser.builder().phoneNumber(request.getUsername()).build()))
|
||||
return R.fail("注册失败," + "手机号'" + request.getUsername() + "'已被注册!");
|
||||
|
||||
String phoneNumber = request.getUsername();
|
||||
String invitationCode = getInvitationCode();
|
||||
String nickName = RandomUtils.getRandomName(new Random().nextInt(2));
|
||||
TtUser ttUser = TtUser.builder().build();
|
||||
ttUser.setUserName(phoneNumber);
|
||||
ttUser.setNickName(nickName);
|
||||
ttUser.setUserType("01");
|
||||
ttUser.setPhoneNumber(phoneNumber);
|
||||
ttUser.setAvatar("");
|
||||
ttUser.setPassword(SecurityUtils.encryptPassword(request.getPassword()));
|
||||
ttUser.setInvitationCode(invitationCode.toLowerCase());
|
||||
ttUser.setIsRealCheck("0");
|
||||
ttUser.setRemark(request.getContactInformation());
|
||||
ttUser.setCreateBy("");
|
||||
ttUser.setCreateTime(DateUtils.getNowDate());
|
||||
ttUser.setAccountAmount(BigDecimal.ZERO);
|
||||
ttUser.setAccountCredits(BigDecimal.ZERO);
|
||||
|
||||
var parentInvitationCode = request.getParentInvitationCode();
|
||||
TtUser parentUser = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
|
||||
.eq(TtUser::getInvitationCode, parentInvitationCode.trim().toUpperCase())
|
||||
.eq(TtUser::getDelFlag, "0").one();
|
||||
if (Objects.isNull(parentUser) || !UserType.BUSINESS_USER.getCode().equals(parentUser.getUserType())) {
|
||||
return R.fail("上级邀请码填写错误!");
|
||||
}
|
||||
ttUser.setParentId(parentUser.getUserId());
|
||||
|
||||
String validateCaptcha = apiSmsService.validateCaptcha(request.getCode().trim(), "ApiRegister_" + phoneNumber);
|
||||
if (!"success".equals(validateCaptcha)) return R.fail(validateCaptcha);
|
||||
|
||||
try {
|
||||
var id = userIdGenerator.generateUserId();
|
||||
ttUser.setUserId(id);
|
||||
ttUserMapper.insert(ttUser);
|
||||
} catch (DuplicateKeyException e) {
|
||||
return R.fail("手机号'" + request.getUsername() + "'已被注册!");
|
||||
} catch (Exception e) {
|
||||
log.error("用户注册失败", e);
|
||||
return R.fail("注册失败,请稍后重试");
|
||||
}
|
||||
ttUser.setPassword(null);
|
||||
return R.ok(ttUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<TtUser> updateInvitationCode(UpdateInvitationCodeRequest request) {
|
||||
// 验证参数
|
||||
if (StringUtils.isEmpty(request.getUsername())) return R.fail("用户名不能为空");
|
||||
if (StringUtils.isEmpty(request.getInvitationCode())) return R.fail("邀请码不能为空");
|
||||
if (request.getInvitationCode().length() != 6) return R.fail("邀请码长度必须为6位");
|
||||
|
||||
// 查找用户
|
||||
TtUser user = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
|
||||
.eq(TtUser::getUserName, request.getUsername())
|
||||
.eq(TtUser::getDelFlag, "0")
|
||||
.one();
|
||||
|
||||
if (Objects.isNull(user)) {
|
||||
return R.fail("用户不存在");
|
||||
}
|
||||
|
||||
// 检查邀请码是否已存在
|
||||
TtUser existingUser = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
|
||||
.eq(TtUser::getInvitationCode, request.getInvitationCode().toLowerCase())
|
||||
.eq(TtUser::getDelFlag, "0")
|
||||
.ne(TtUser::getUserId, user.getUserId()) // 排除当前用户
|
||||
.one();
|
||||
|
||||
if (Objects.nonNull(existingUser)) {
|
||||
return R.fail("邀请码已存在,请更换其他邀请码");
|
||||
}
|
||||
|
||||
// 更新邀请码
|
||||
try {
|
||||
boolean updated = new LambdaUpdateChainWrapper<>(ttUserMapper)
|
||||
.eq(TtUser::getUserId, user.getUserId())
|
||||
.set(TtUser::getInvitationCode, request.getInvitationCode().toLowerCase())
|
||||
.update();
|
||||
|
||||
|
||||
if (!updated) {
|
||||
return R.fail("更新邀请码失败");
|
||||
}
|
||||
|
||||
// 重新获取用户信息
|
||||
user = new LambdaQueryChainWrapper<>(userService.getBaseMapper())
|
||||
.eq(TtUser::getUserId, user.getUserId())
|
||||
.one();
|
||||
user.setPassword(null); // 清除密码
|
||||
return R.ok(user);
|
||||
} catch (Exception e) {
|
||||
log.error("更新邀请码失败", e);
|
||||
return R.fail("更新邀请码失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<GetShareDomainResponse> getShareDomain() {
|
||||
GetShareDomainResponse resp = new GetShareDomainResponse();
|
||||
SysConfig zhubo = sysConfigMapper.checkConfigKeyUnique("app.zhubo.sharelink");
|
||||
SysConfig zhaoshang = sysConfigMapper.checkConfigKeyUnique("app.zhaoshang.sharelink");
|
||||
if (zhubo != null) {
|
||||
resp.setZhuboShareDomain(zhubo.getConfigValue());
|
||||
}
|
||||
if (zhaoshang != null) {
|
||||
resp.setZhaoshaoShareDomain(zhaoshang.getConfigValue());
|
||||
}
|
||||
return R.ok(resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtRechargeProd> queryList() {
|
||||
LambdaQueryWrapper<TtRechargeProd> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.ge(TtRechargeProd::getPrice, BigDecimal.valueOf(100));
|
||||
return rechargeListMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> generateCard(Integer userId, Integer rechargeListId, Integer num) {
|
||||
if (num <= 0) return new ArrayList<>();
|
||||
TtRechargeProd recharge = rechargeListMapper.selectById(rechargeListId);
|
||||
if (recharge == null) return new ArrayList<>();
|
||||
|
||||
BigDecimal totalPrice = recharge.getPrice().multiply(BigDecimal.valueOf(num));
|
||||
var r = userService.updateUserCredits(userId, totalPrice.negate(), TtAccountRecordSource.ZHUBO_EXTRACT);
|
||||
if (R.isError(r)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
List<String> cardList = new ArrayList<>();
|
||||
List<TtRedPacket> rpList = new ArrayList<>();
|
||||
for (int i = 0; i < num; i++) {
|
||||
|
||||
TtRedPacket redPacket = new TtRedPacket();
|
||||
redPacket.setNum(1);
|
||||
redPacket.setUserId(userId);
|
||||
redPacket.setTitle("福利");
|
||||
redPacket.setOpeningTime(DateUtils.getNowDate());
|
||||
redPacket.setAmount(String.format("[%s,%s]", recharge.getPrice().toPlainString(), recharge.getPrice().toPlainString()));
|
||||
redPacket.setPassword(IdUtils.fastSimpleUUID().toUpperCase());
|
||||
cardList.add(redPacket.getPassword());
|
||||
redPacket.setCreateBy(SecurityUtils.getUsername());
|
||||
redPacket.setCreateTime(DateUtils.getNowDate());
|
||||
redPacket.setUseStatus(0);
|
||||
rpList.add(redPacket);
|
||||
}
|
||||
|
||||
redPacketMapper.insert(rpList);
|
||||
|
||||
return cardList;
|
||||
}
|
||||
|
||||
public String getInvitationCode() {
|
||||
while (true) {
|
||||
try {
|
||||
String randomInvitationCode = UUID.randomUUID().toString().replace("-", "").substring(0, 6).toUpperCase();
|
||||
TtUser ttUser = new LambdaQueryChainWrapper<>(ttUserMapper)
|
||||
.eq(TtUser::getInvitationCode, randomInvitationCode)
|
||||
.eq(TtUser::getDelFlag, "0")
|
||||
.one();
|
||||
if (StringUtils.isNull(ttUser)) {
|
||||
return randomInvitationCode;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*/
|
||||
public void recordLoginInfo(Long userId) {
|
||||
new LambdaUpdateChainWrapper<>(ttUserMapper).eq(TtUser::getUserId, userId)
|
||||
.set(TtUser::getLoginIp, IpUtils.getIpAddr())
|
||||
.set(TtUser::getLoginDate, DateUtils.getNowDate()).update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
package com.ruoyi.promo.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.admin.mapper.TtUserBlendErcashMapper;
|
||||
import com.ruoyi.admin.mapper.TtUserMapper;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.DateTimeUtils;
|
||||
import com.ruoyi.common.utils.bean.BeanUtils;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordSource;
|
||||
import com.ruoyi.domain.common.constant.TtAccountRecordType;
|
||||
import com.ruoyi.domain.entity.TtCommissionRecord;
|
||||
import com.ruoyi.domain.entity.TtUserBlendErcash;
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.promo.contract.request.GetPurchaseByUserIdRequest;
|
||||
import com.ruoyi.promo.contract.request.GetSubBranchesRequest;
|
||||
import com.ruoyi.promo.contract.request.QueryPromoteWelfareRequest;
|
||||
import com.ruoyi.promo.contract.response.GetSubBranchesResponse;
|
||||
import com.ruoyi.promo.contract.response.QueryPromotionWelfareResponse;
|
||||
import com.ruoyi.promo.contract.vo.DailyUserErcashVO;
|
||||
import com.ruoyi.promo.domain.dto.AnchorDayTurnoverDTO;
|
||||
import com.ruoyi.promo.domain.param.GetPlayersTurnoverParam;
|
||||
import com.ruoyi.promo.domain.vo.AnchorDayTurnoverVO;
|
||||
import com.ruoyi.promo.domain.vo.DayInviteVO;
|
||||
import com.ruoyi.promo.domain.vo.DayTurnoverVO;
|
||||
import com.ruoyi.promo.mapper.PromoTurnoverMapper;
|
||||
import com.ruoyi.promo.service.PromoTurnoverService;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class PromoTurnoverServiceImpl implements PromoTurnoverService {
|
||||
|
||||
@Autowired
|
||||
private PromoTurnoverMapper promoTurnoverMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserBlendErcashMapper userBlendErcashMapper;
|
||||
|
||||
@Autowired
|
||||
private TtUserMapper userMapper;
|
||||
|
||||
@Override
|
||||
public AjaxResult getRealTimeData(Integer userId) {
|
||||
// 递归名下所有玩家
|
||||
List<TtUser> allPlayer = recursionAllPlayer(userId);
|
||||
List<Integer> userIds = new ArrayList<>();
|
||||
for (TtUser ttUser : allPlayer) {
|
||||
userIds.add(ttUser.getUserId());
|
||||
}
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
if (CollectionUtils.isEmpty(userIds)) {
|
||||
map.put("anchorCount", 0);
|
||||
map.put("totalTurnover", BigDecimal.ZERO);
|
||||
map.put("lastMonthTurnover", BigDecimal.ZERO);
|
||||
map.put("currentMonthTurnover", BigDecimal.ZERO);
|
||||
map.put("lastWeekTurnover", BigDecimal.ZERO);
|
||||
map.put("currentWeekTurnover", BigDecimal.ZERO);
|
||||
map.put("lastDayTurnover", BigDecimal.ZERO);
|
||||
map.put("currentDayTurnover", BigDecimal.ZERO);
|
||||
return AjaxResult.success(map);
|
||||
}
|
||||
// 设置日期转换为字符串格式
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
// 查询名下主播数
|
||||
map.put("anchorCount", promoTurnoverMapper.getAnchorCount(userId));
|
||||
// 查询总消费流水
|
||||
GetPlayersTurnoverParam param = new GetPlayersTurnoverParam();
|
||||
param.setUserIds(userIds);
|
||||
param.setSourceCodes(new ArrayList<>(TtAccountRecordSource.getWelfarePrizeCodes()));
|
||||
BigDecimal totalTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("totalTurnover", totalTurnover);
|
||||
|
||||
// 查询上个月消费流水
|
||||
Date lastMonthStartTime = getStartOfLastMonth().getTime();
|
||||
Date lastMonthEndTime = getEndOfLastMonth().getTime();
|
||||
param.setBeginTime(sdf.format(lastMonthStartTime));
|
||||
param.setEndTime(sdf.format(lastMonthEndTime));
|
||||
BigDecimal lastMonthTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("lastMonthTurnover", lastMonthTurnover);
|
||||
|
||||
// 查询当月消费流水
|
||||
Date currentMonthStartTime = getStartOfThisMonth().getTime();
|
||||
param.setBeginTime(sdf.format(currentMonthStartTime));
|
||||
param.setEndTime(null);
|
||||
param.setBeginTime(sdf.format(currentMonthStartTime));
|
||||
param.setEndTime(null);
|
||||
BigDecimal currentMonthTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("currentMonthTurnover", currentMonthTurnover);
|
||||
|
||||
// 查询上周消费流水
|
||||
Date lastWeekStartTime = getStartOfLastWeek().getTime();
|
||||
Date lastWeekEndTime = getEndOfLastWeek().getTime();
|
||||
param.setBeginTime(sdf.format(lastWeekStartTime));
|
||||
param.setEndTime(sdf.format(lastWeekEndTime));
|
||||
BigDecimal lastWeekTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("lastWeekTurnover", lastWeekTurnover);
|
||||
|
||||
// 查询本周消费流水
|
||||
Date currentWeekStartTime = getStartOfThisWeek().getTime();
|
||||
param.setBeginTime(sdf.format(currentWeekStartTime));
|
||||
param.setEndTime(null);
|
||||
BigDecimal currentWeekTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("currentWeekTurnover", currentWeekTurnover);
|
||||
|
||||
// 查询昨天消费流水
|
||||
Date yesterdayStartTime = getStartOfYesterday().getTime();
|
||||
Date yesterdayEndTime = getEndOfYesterday().getTime();
|
||||
param.setBeginTime(sdf.format(yesterdayStartTime));
|
||||
param.setEndTime(sdf.format(yesterdayEndTime));
|
||||
BigDecimal lastDayTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("lastDayTurnover", lastDayTurnover);
|
||||
|
||||
// 查询当天消费流水
|
||||
Date currentDayStartTime = getStartOfToday().getTime();
|
||||
param.setBeginTime(sdf.format(currentDayStartTime));
|
||||
param.setEndTime(null);
|
||||
BigDecimal currentDayTurnover = promoTurnoverMapper.getPlayersTurnover(param);
|
||||
map.put("currentDayTurnover", currentDayTurnover);
|
||||
|
||||
return AjaxResult.success(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult getLast10DaysPromotionData(Integer userId) {
|
||||
// 递归名下所有玩家
|
||||
List<TtUser> allPlayer = recursionAllPlayer(userId);
|
||||
List<Integer> userIds = new ArrayList<>();
|
||||
for (TtUser ttUser : allPlayer) {
|
||||
userIds.add(ttUser.getUserId());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(userIds)) {
|
||||
return AjaxResult.success();
|
||||
}
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
List<DayTurnoverVO> last10DaysTurnoverVOList = promoTurnoverMapper.getLast10DaysTurnover(userIds,new ArrayList<>(TtAccountRecordSource.getWelfarePrizeCodes()));
|
||||
List<DayInviteVO> last10DaysAnchorVOList = promoTurnoverMapper.getLast10DaysInvite(userId);
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (DayTurnoverVO last10DaysTurnoverVO : last10DaysTurnoverVOList) {
|
||||
for (DayInviteVO last10DaysAnchorVO : last10DaysAnchorVOList) {
|
||||
if (last10DaysTurnoverVO.getDate().equals(last10DaysAnchorVO.getDate())) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("date", dateFormat.format(last10DaysTurnoverVO.getDate()));
|
||||
map.put("last10DaysTurnover", last10DaysTurnoverVO.getAmount());
|
||||
map.put("last10DaysAnchorInvite", last10DaysAnchorVO.getAnchorCount());
|
||||
list.add(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnchorDayTurnoverVO> getAnchorDayTurnover(AnchorDayTurnoverDTO anchorDayTurnoverDTO) {
|
||||
// 递归名下所有玩家
|
||||
Integer userId = anchorDayTurnoverDTO.getUserId();
|
||||
List<TtUser> allPlayer = recursionAllPlayer(userId);
|
||||
List<Integer> userIds = new ArrayList<>();
|
||||
for (TtUser ttUser : allPlayer) {
|
||||
userIds.add(ttUser.getUserId());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(userIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
anchorDayTurnoverDTO.setUserIds(userIds);
|
||||
anchorDayTurnoverDTO.setSourceCodes(new ArrayList<>(TtAccountRecordSource.getWelfarePrizeCodes()));
|
||||
|
||||
List<AnchorDayTurnoverVO> result = promoTurnoverMapper.getAnchorDayTurnover(anchorDayTurnoverDTO);
|
||||
for (AnchorDayTurnoverVO anchorDayTurnoverVO : result) {
|
||||
Date startDate = anchorDayTurnoverVO.getDate();
|
||||
Date endDate = DateTimeUtils.addDays(startDate, 1);
|
||||
BigDecimal dailyTotalRecharge = promoTurnoverMapper.getDailyTotalRecharge(anchorDayTurnoverVO.getUserId(), startDate, endDate);
|
||||
anchorDayTurnoverVO.setDailyRechargeTotal(dailyTotalRecharge == null ? BigDecimal.ZERO : dailyTotalRecharge);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetSubBranchesResponse getSubBranches(GetSubBranchesRequest request) {
|
||||
if (request.getPageNum() == null || request.getPageNum() <= 0) {
|
||||
request.setPageNum(1);
|
||||
}
|
||||
if (request.getPageSize() == null || request.getPageSize() <= 0) {
|
||||
request.setPageSize(10);
|
||||
}
|
||||
Long userId = Long.valueOf(request.getUserId());
|
||||
var query = new LambdaQueryChainWrapper<>(userMapper).eq(TtUser::getParentId, userId);
|
||||
|
||||
if (request.getPlayerId() != null) {
|
||||
query.eq(TtUser::getUserId, request.getPlayerId());
|
||||
}
|
||||
|
||||
Page<TtUser> page = new Page<>(request.getPageNum(), request.getPageSize());
|
||||
page.setOptimizeCountSql(false);
|
||||
|
||||
var pageData = query.page(page);
|
||||
|
||||
var childrenList = pageData.getRecords();
|
||||
|
||||
if (CollectionUtils.isEmpty(childrenList)) {
|
||||
GetSubBranchesResponse response = new GetSubBranchesResponse();
|
||||
response.setTotal((int) page.getTotal());
|
||||
response.setRows(new ArrayList<>());
|
||||
return response;
|
||||
}
|
||||
|
||||
List<Integer> userids = childrenList.stream().map(TtUser::getUserId).collect(Collectors.toList());
|
||||
List<TtUserBlendErcash> ercashList = new LambdaQueryChainWrapper<>(userBlendErcashMapper)
|
||||
.in(TtUserBlendErcash::getSource, TtAccountRecordSource.getWelfarePrizeCodes())
|
||||
.in(TtUserBlendErcash::getUserId, userids).list();
|
||||
Map<Integer, List<TtUserBlendErcash>> ercashMap = ercashList.stream()
|
||||
.collect(Collectors.groupingBy(TtUserBlendErcash::getUserId));
|
||||
|
||||
List<GetSubBranchesResponse.UserInfo> resultList = childrenList.stream().map(user -> {
|
||||
GetSubBranchesResponse.UserInfo userInfo = new GetSubBranchesResponse.UserInfo();
|
||||
BeanUtils.copyProperties(user, userInfo);
|
||||
|
||||
userInfo.setTotalCost(BigDecimal.ZERO);
|
||||
userInfo.setTotalRecharge(BigDecimal.ZERO);
|
||||
|
||||
if (ercashMap.containsKey(user.getUserId())) {
|
||||
var records = ercashMap.get(user.getUserId());
|
||||
|
||||
var totalRecharge = records.stream().filter(v -> {
|
||||
return Objects.equals(v.getSource(), TtAccountRecordSource.RECHARGE.getCode());
|
||||
}).map(v -> v.getAmount().abs()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
var allConsumeList = records.stream().filter(v -> {
|
||||
return Objects.equals(v.getType(), TtAccountRecordType.OUTPUT.getCode());
|
||||
}).toList();
|
||||
|
||||
var totalNormalGameConsume = allConsumeList.stream().filter(v -> {
|
||||
return TtAccountRecordSource.isNormalGameConsume(v.getSource());
|
||||
}).map(v -> v.getAmount().abs()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
var totalSpecialGameConsume = allConsumeList.stream().filter(v -> {
|
||||
return TtAccountRecordSource.isSpecialGameConsume(v.getSource());
|
||||
}).map(v -> v.getAmount().abs()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
|
||||
userInfo.setTotalNormGameCost(totalNormalGameConsume);
|
||||
userInfo.setTotalSpecialGameCost(totalSpecialGameConsume);
|
||||
userInfo.setTotalRecharge(totalRecharge);
|
||||
}
|
||||
|
||||
return userInfo;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
GetSubBranchesResponse response = new GetSubBranchesResponse();
|
||||
response.setTotal((int) page.getTotal());
|
||||
response.setRows(resultList);
|
||||
return response;
|
||||
}
|
||||
|
||||
private Set<TtUser> findAllChild(Integer parentId, Set<TtUser> result) {
|
||||
|
||||
List<TtUser> list = promoTurnoverMapper.findByParentId(parentId);
|
||||
HashSet<TtUser> childrens = new HashSet<>(list);
|
||||
|
||||
if (childrens.isEmpty()) return result;
|
||||
|
||||
result.addAll(childrens);
|
||||
for (TtUser child : childrens) {
|
||||
Set<TtUser> allChild = findAllChild(child.getUserId(), result);
|
||||
result.addAll(allChild);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataInfo getPurchaseByUserId(GetPurchaseByUserIdRequest request) {
|
||||
if (request.getPageNum() == null || request.getPageNum() <= 0) {
|
||||
request.setPageNum(1);
|
||||
}
|
||||
if (request.getPageSize() == null || request.getPageSize() <= 0) {
|
||||
request.setPageSize(10);
|
||||
}
|
||||
if (request.getBeginTime() == null) {
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
LocalDateTime startTime = endTime.minusDays(30).with(LocalTime.MIN);
|
||||
request.setBeginTime(DateTimeUtils.date(startTime));
|
||||
}
|
||||
if (request.getEndTime() == null) {
|
||||
LocalDateTime endTime = LocalDateTime.now();
|
||||
request.setEndTime(DateTimeUtils.date(endTime));
|
||||
}
|
||||
// Limit the time range to maximum 30 days
|
||||
if (request.getBeginTime() != null && request.getEndTime() != null) {
|
||||
LocalDateTime begin = DateTimeUtils.toLocalDateTime(DateTimeUtils.dateTime(DateTimeUtils.YYYY_MM_DD, request.getBeginTime()));
|
||||
LocalDateTime end = DateTimeUtils.toLocalDateTime(DateTimeUtils.dateTime(DateTimeUtils.YYYY_MM_DD, request.getEndTime()));
|
||||
if (ChronoUnit.DAYS.between(begin, end) > 30) {
|
||||
LocalDateTime adjustedEnd = begin.plusDays(30);
|
||||
request.setEndTime(DateTimeUtils.date(adjustedEnd));
|
||||
}
|
||||
}
|
||||
|
||||
List<String> days = DateTimeUtils.generateDailyDates(request.getBeginTime(), request.getEndTime());
|
||||
days.sort(Comparator.reverseOrder());
|
||||
|
||||
int total = days.size();
|
||||
int start = Math.min((request.getPageNum() - 1) * request.getPageSize(), total - 1);
|
||||
int end = Math.min(start + request.getPageSize(), total);
|
||||
start = Math.max(start, 0);
|
||||
end = Math.max(end, 0);
|
||||
days = days.subList(start, end);
|
||||
|
||||
|
||||
|
||||
List<DailyUserErcashVO> resultList = days.stream().map(d -> {
|
||||
var records = new LambdaQueryChainWrapper<>(userBlendErcashMapper)
|
||||
.eq(TtUserBlendErcash::getUserId, request.getUserId())
|
||||
.apply("DATE(create_time) = {0}", d)
|
||||
.in(TtUserBlendErcash::getSource, TtAccountRecordSource.getWelfarePrizeCodes())
|
||||
.list();
|
||||
var totalRecharge = records.stream().filter(v -> {
|
||||
return Objects.equals(v.getSource(), TtAccountRecordSource.RECHARGE.getCode());
|
||||
}).map(v -> v.getAmount().abs()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
var allConsumeList = records.stream().filter(v -> {
|
||||
return Objects.equals(v.getType(), TtAccountRecordType.OUTPUT.getCode());
|
||||
}).toList();
|
||||
|
||||
var totalNormalGameConsume = allConsumeList.stream().filter(v -> {
|
||||
return TtAccountRecordSource.isNormalGameConsume(v.getSource());
|
||||
}).map(v -> v.getAmount().abs()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
var totalSpecialGameConsume = allConsumeList.stream().filter(v -> {
|
||||
return TtAccountRecordSource.isSpecialGameConsume(v.getSource());
|
||||
}).map(v -> v.getAmount().abs()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
DailyUserErcashVO r = new DailyUserErcashVO();
|
||||
r.setDate(d);
|
||||
r.setDailyNormGameCost(totalNormalGameConsume);
|
||||
r.setDailySpecialGameCost(totalSpecialGameConsume);
|
||||
r.setDailyRecharge(totalRecharge);
|
||||
return r;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
TableDataInfo result = new TableDataInfo();
|
||||
result.setCode(200);
|
||||
result.setRows(resultList);
|
||||
result.setTotal(total);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal getCommissionRateByUserId(Integer userId) {
|
||||
return promoTurnoverMapper.getCommissionRateByUserId(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateCommissionRate(Integer userId, BigDecimal commissionRate) {
|
||||
return promoTurnoverMapper.updateCommissionRate(userId, commissionRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtCommissionRecord> getCommissionList(Integer userId) {
|
||||
return promoTurnoverMapper.getCommissionList(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryPromotionWelfareResponse queryPromoteWelfare(Integer userId, QueryPromoteWelfareRequest request) {
|
||||
Page<TtUserBlendErcash> page = new Page<>(request.getPageNum(), request.getPageSize());
|
||||
page.setOptimizeCountSql(false);
|
||||
|
||||
LambdaQueryChainWrapper<TtUserBlendErcash> wrapper = new LambdaQueryChainWrapper<>(userBlendErcashMapper)
|
||||
.eq(TtUserBlendErcash::getUserId, userId)
|
||||
.eq(TtUserBlendErcash::getSource, TtAccountRecordSource.P_WELFARE.getCode());
|
||||
|
||||
if (request.getBeginTime() != null) {
|
||||
wrapper.ge(TtUserBlendErcash::getCreateTime, request.getBeginTime());
|
||||
}
|
||||
if (request.getEndTime() != null) {
|
||||
wrapper.le(TtUserBlendErcash::getCreateTime, request.getEndTime());
|
||||
}
|
||||
wrapper.orderByDesc(TtUserBlendErcash::getCreateTime);
|
||||
Page<TtUserBlendErcash> pageResult = wrapper.page(page);
|
||||
|
||||
BigDecimal totalReward = promoTurnoverMapper.queryTotalRewardBySource(userId, TtAccountRecordSource.P_WELFARE.getCode());
|
||||
if (totalReward == null) {
|
||||
totalReward = BigDecimal.ZERO;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(pageResult.getRecords())) {
|
||||
QueryPromotionWelfareResponse result = new QueryPromotionWelfareResponse();
|
||||
result.setRows(new ArrayList<>());
|
||||
result.setTotal(0);
|
||||
result.setTotalReward(totalReward);
|
||||
return result;
|
||||
}
|
||||
|
||||
QueryPromotionWelfareResponse result = new QueryPromotionWelfareResponse();
|
||||
result.setRows(pageResult.getRecords().stream().map(v -> {
|
||||
QueryPromotionWelfareResponse.Record r = new QueryPromotionWelfareResponse.Record();
|
||||
r.setReward(v.getAmount());
|
||||
r.setDate(DateTimeUtils.dateTime(v.getCreateTime().toLocalDateTime()));
|
||||
return r;
|
||||
}).collect(Collectors.toList()));
|
||||
result.setTotalReward(totalReward);
|
||||
result.setTotal((int) pageResult.getTotal());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归下级分支
|
||||
*/
|
||||
private void buildUserTree(TtUser ttUser) {
|
||||
// 获取当前用户的子节点
|
||||
List<TtUser> children = promoTurnoverMapper.findByParentId(ttUser.getUserId());
|
||||
// 设置当前用户的子节点
|
||||
ttUser.setChildren(children);
|
||||
for (TtUser child : children) {
|
||||
// 如果子节点是主播,继续递归
|
||||
if ("01".equals(child.getUserType())) {
|
||||
buildUserTree(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtUser> recursionAllPlayer(Integer userId) {
|
||||
List<TtUser> players = new ArrayList<>();
|
||||
getAllPlayersByAnchorIdRecursive(userId, players);
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归名下所有玩家
|
||||
*/
|
||||
private void getAllPlayersByAnchorIdRecursive(int parentId, List<TtUser> players) {
|
||||
List<TtUser> users = promoTurnoverMapper.findByParentId(parentId);
|
||||
for (TtUser user : users) {
|
||||
if ("02".equals(user.getUserType())) { // 如果是玩家
|
||||
players.add(user);
|
||||
} else if ("01".equals(user.getUserType())) { // 如果是主播,继续递归
|
||||
getAllPlayersByAnchorIdRecursive(user.getUserId(), players);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Calendar getStartOfLastMonth() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
resetTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getEndOfLastMonth() {
|
||||
Calendar calendar = getStartOfLastMonth();
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
setTimeToEndOfDay(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getStartOfThisMonth() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
resetTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getStartOfLastWeek() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.WEEK_OF_YEAR, -1);
|
||||
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
|
||||
resetTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getEndOfLastWeek() {
|
||||
Calendar calendar = getStartOfLastWeek();
|
||||
calendar.add(Calendar.DAY_OF_WEEK, 6);
|
||||
setTimeToEndOfDay(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getStartOfThisWeek() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.DAY_OF_WEEK, calendar.getFirstDayOfWeek());
|
||||
resetTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getStartOfYesterday() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
resetTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getEndOfYesterday() {
|
||||
Calendar calendar = getStartOfYesterday();
|
||||
setTimeToEndOfDay(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private Calendar getStartOfToday() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
resetTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
private void resetTime(Calendar calendar) {
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
}
|
||||
|
||||
private void setTimeToEndOfDay(Calendar calendar) {
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
||||
calendar.set(Calendar.MINUTE, 59);
|
||||
calendar.set(Calendar.SECOND, 59);
|
||||
calendar.set(Calendar.MILLISECOND, 999);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.ruoyi.promo.task;
|
||||
|
||||
import com.ruoyi.domain.entity.sys.TtUser;
|
||||
import com.ruoyi.promo.domain.dto.TotalUserExpenditureDTO;
|
||||
import com.ruoyi.promo.mapper.PromoTurnoverMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
@Slf4j
|
||||
@Component("PromoTask")
|
||||
public class PromoTask {
|
||||
|
||||
@Autowired
|
||||
private PromoTurnoverMapper promoTurnoverMapper;
|
||||
|
||||
private Map<Integer, BigDecimal> commissionMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 计算上月佣金
|
||||
*/
|
||||
public void calculateLastMonthCommission() {
|
||||
// 汇总所有用户上个月的充值总额
|
||||
List<TotalUserExpenditureDTO> lastMonthTotalUserExpenditure = promoTurnoverMapper.getLastMonthTotalUserExpenditure();
|
||||
for (TotalUserExpenditureDTO totalUserExpenditureDTO : lastMonthTotalUserExpenditure) {
|
||||
// 向上递归给各级代理分配佣金
|
||||
if (!Objects.isNull(totalUserExpenditureDTO.getParentId())) {
|
||||
distributeCommission(totalUserExpenditureDTO.getParentId(),
|
||||
totalUserExpenditureDTO.getCommissionRate(),
|
||||
totalUserExpenditureDTO.getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分配佣金
|
||||
*/
|
||||
private void distributeCommission(Integer parentId,
|
||||
BigDecimal commissionRate,
|
||||
BigDecimal amount) {
|
||||
TtUser ttUser = promoTurnoverMapper.findById(parentId);
|
||||
BigDecimal parentCommissionRate = ttUser.getCommissionRate();
|
||||
BigDecimal commission = parentCommissionRate.multiply(amount).subtract(commissionRate.multiply(amount));
|
||||
System.err.println("代理:" + parentId + ",佣金比例:" + parentCommissionRate + ",获得佣金:" + commission);
|
||||
// 计算并存储该级代理的佣金
|
||||
// 将相同ID的代理佣金相加
|
||||
// 判断是否还有上级代理,有继续递归
|
||||
if (!Objects.isNull(ttUser.getParentId())) {
|
||||
distributeCommission(ttUser.getParentId(),
|
||||
ttUser.getCommissionRate(),
|
||||
amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
<?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.ruoyi.promo.mapper.PromoTurnoverMapper">
|
||||
|
||||
<select id="getAnchorCount" parameterType="Integer" resultType="int">
|
||||
SELECT COUNT(*) FROM tt_user WHERE parent_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="getPlayersTurnover"
|
||||
parameterType="com.ruoyi.promo.domain.param.GetPlayersTurnoverParam"
|
||||
resultType="BigDecimal">
|
||||
SELECT
|
||||
SUM(ABS(total))
|
||||
FROM
|
||||
tt_user_blend_ercash
|
||||
WHERE
|
||||
type = 0
|
||||
<if test="sourceCodes != null and sourceCodes.size() > 0">
|
||||
AND source IN
|
||||
<foreach item="code" collection="sourceCodes" open="(" separator="," close=")">
|
||||
#{code}
|
||||
</foreach>
|
||||
</if>
|
||||
AND user_id IN
|
||||
<foreach item="id" index="index" collection="userIds" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
<if test="beginTime != null and beginTime != ''">
|
||||
AND create_time >= #{beginTime}
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
AND create_time <= #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getLast10DaysTurnover" parameterType="List" resultType="com.ruoyi.promo.domain.vo.DayTurnoverVO">
|
||||
SELECT
|
||||
date_range.date,
|
||||
IFNULL(SUM(ABS(tt_user_blend_ercash.amount)), 0) AS amount
|
||||
FROM
|
||||
(
|
||||
SELECT CURDATE() - INTERVAL 10 DAY AS date
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 9 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 8 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 7 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 6 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 5 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 4 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 3 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 2 DAY
|
||||
UNION ALL
|
||||
SELECT CURDATE() - INTERVAL 1 DAY
|
||||
) AS date_range
|
||||
LEFT JOIN tt_user_blend_ercash ON DATE(tt_user_blend_ercash.create_time) = date_range.date
|
||||
AND tt_user_blend_ercash.type = '0'
|
||||
<if test="sourceCodes != null and sourceCodes.size() > 0">
|
||||
AND tt_user_blend_ercash.source IN
|
||||
<foreach item="code" collection="sourceCodes" open="(" separator="," close=")">
|
||||
#{code}
|
||||
</foreach>
|
||||
</if>
|
||||
AND tt_user_blend_ercash.user_id IN
|
||||
<foreach item="id" collection="userIds" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
GROUP BY date_range.date
|
||||
</select>
|
||||
|
||||
<select id="getLast10DaysInvite" parameterType="Integer" resultType="com.ruoyi.promo.domain.vo.DayInviteVO">
|
||||
SELECT
|
||||
DATE(date_range.date) AS date,
|
||||
COUNT(tt_user.user_id) AS anchorCount
|
||||
FROM
|
||||
(
|
||||
SELECT CURDATE() - INTERVAL (a.a + 1) DAY AS date
|
||||
FROM
|
||||
(
|
||||
SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
|
||||
) AS a
|
||||
) AS date_range
|
||||
LEFT JOIN tt_user ON DATE(tt_user.create_time) = DATE(date_range.date)
|
||||
AND tt_user.user_type = '02'
|
||||
AND tt_user.parent_id IN
|
||||
(
|
||||
SELECT user_id
|
||||
FROM tt_user
|
||||
WHERE user_type = '01'
|
||||
AND parent_id = #{userId}
|
||||
)
|
||||
GROUP BY DATE(date_range.date)
|
||||
ORDER BY DATE(date_range.date)
|
||||
</select>
|
||||
|
||||
<select id="getAnchorDayTurnover" parameterType="com.ruoyi.promo.domain.dto.AnchorDayTurnoverDTO" resultType="com.ruoyi.promo.domain.vo.AnchorDayTurnoverVO">
|
||||
SELECT
|
||||
daily.user_id,
|
||||
daily.parent_id,
|
||||
daily.nick_name,
|
||||
tu_parent.nick_name AS parent_nick_name,
|
||||
daily.daily_total,
|
||||
daily.date,
|
||||
total.total_by_parent
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
tube.user_id,
|
||||
tu.parent_id,
|
||||
tu.nick_name,
|
||||
SUM(ABS(tube.total)) AS daily_total,
|
||||
DATE(tube.create_time) AS date
|
||||
FROM
|
||||
tt_user_blend_ercash AS tube
|
||||
LEFT JOIN
|
||||
tt_user AS tu ON tube.user_id = tu.user_id
|
||||
LEFT JOIN
|
||||
tt_user AS tu_parent ON tu.parent_id = tu_parent.user_id
|
||||
WHERE
|
||||
tube.type = 0
|
||||
AND tube.user_id IN
|
||||
<foreach item="id" index="index" collection="userIds" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
<if test="sourceCodes != null and sourceCodes.size() > 0">
|
||||
AND tube.source IN
|
||||
<foreach item="code" collection="sourceCodes" open="(" separator="," close=")">
|
||||
#{code}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="parentId != null">
|
||||
AND tu.parent_id = #{parentId}
|
||||
</if>
|
||||
<if test="parentNickName != null and parentNickName != ''">
|
||||
AND tu_parent.nick_name like concat('%', #{parentNickName}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''">
|
||||
AND date_format(tube.create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
AND date_format(tube.create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
</if>
|
||||
GROUP BY
|
||||
tube.user_id, tu.parent_id, DATE(tube.create_time)
|
||||
) AS daily
|
||||
JOIN
|
||||
(
|
||||
SELECT
|
||||
tu.parent_id,
|
||||
SUM(ABS(tube.total)) AS total_by_parent
|
||||
FROM
|
||||
tt_user_blend_ercash AS tube
|
||||
LEFT JOIN
|
||||
tt_user AS tu ON tube.user_id = tu.user_id
|
||||
LEFT JOIN
|
||||
tt_user AS tu_parent ON tu.parent_id = tu_parent.user_id
|
||||
WHERE
|
||||
tube.type = 0
|
||||
AND tube.user_id IN
|
||||
<foreach item="id" index="index" collection="userIds" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
<if test="sourceCodes != null and sourceCodes.size() > 0">
|
||||
AND tube.source IN
|
||||
<foreach item="code" collection="sourceCodes" open="(" separator="," close=")">
|
||||
#{code}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="parentId != null">
|
||||
AND tu.parent_id = #{parentId}
|
||||
</if>
|
||||
<if test="parentNickName != null and parentNickName != ''">
|
||||
AND tu_parent.nick_name like concat('%', #{parentNickName}, '%')
|
||||
</if>
|
||||
<if test="beginTime != null and beginTime != ''">
|
||||
AND date_format(tube.create_time,'%y%m%d') >= date_format(#{beginTime},'%y%m%d')
|
||||
</if>
|
||||
<if test="endTime != null and endTime != ''">
|
||||
AND date_format(tube.create_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
|
||||
</if>
|
||||
GROUP BY
|
||||
tu.parent_id
|
||||
) AS total
|
||||
ON
|
||||
daily.parent_id = total.parent_id
|
||||
JOIN
|
||||
tt_user AS tu_parent ON daily.parent_id = tu_parent.user_id
|
||||
ORDER BY
|
||||
daily.date DESC
|
||||
</select>
|
||||
|
||||
<select id="getPurchaseByUserId" parameterType="Integer" resultType="com.ruoyi.domain.entity.TtUserBlendErcash">
|
||||
SELECT * FROM tt_user_blend_ercash WHERE type = 0 AND user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="getCommissionRateByUserId" parameterType="Integer" resultType="BigDecimal">
|
||||
SELECT commission_rate FROM tt_user WHERE user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<update id="updateCommissionRate">
|
||||
UPDATE tt_user SET commission_rate = #{commissionRate} WHERE user_id = #{userId}
|
||||
</update>
|
||||
|
||||
<select id="getCommissionList" parameterType="Integer" resultType="com.ruoyi.domain.entity.TtCommissionRecord">
|
||||
SELECT * FROM tt_commission_record WHERE user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="getLastMonthTotalUserExpenditure" resultType="com.ruoyi.promo.domain.dto.TotalUserExpenditureDTO">
|
||||
SELECT
|
||||
tu.user_id, tu.user_name, tu.user_type, tu.parent_id, tu.commission_rate,
|
||||
SUM(ABS(tube.amount)) AS amount
|
||||
FROM
|
||||
tt_user AS tu
|
||||
LEFT JOIN
|
||||
tt_user_blend_ercash AS tube ON tu.user_id = tube.user_id
|
||||
WHERE
|
||||
tu.user_type = 02
|
||||
AND tube.type = 0
|
||||
AND tube.create_time >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
|
||||
AND tube.create_time < DATE_FORMAT(CURDATE(), '%Y-%m-01')
|
||||
GROUP BY
|
||||
tu.user_id
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user