This commit is contained in:
777
2025-12-03 16:52:17 +08:00
parent 46a039a678
commit c91ede94a1
22 changed files with 555 additions and 11 deletions

View File

@@ -4,3 +4,57 @@ ALTER TABLE cai_goods
ADD COLUMN `give_point` bigint(20) default 0 not null comment '充值赠送积分'; ADD COLUMN `give_point` bigint(20) default 0 not null comment '充值赠送积分';
ALTER TABLE cai_recharge_order ALTER TABLE cai_recharge_order
ADD COLUMN `distribution` tinyint default 0 not null comment '是否參與分銷'; ADD COLUMN `distribution` tinyint default 0 not null comment '是否參與分銷';
ALTER TABLE cai_user_info
ADD COLUMN point_rate decimal(7, 2) default 0.00 not null comment '积分分销比例';
ALTER TABLE cai_recharge_order
ADD COLUMN `give_point` bigint(20) default 0 not null comment '充值赠送积分';
CREATE TABLE `cai_point_record_log`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`points` bigint(20) DEFAULT 0 COMMENT '积分',
`source_user_id` bigint(20) COMMENT '消费方用户',
`source_usercode` varchar(20) COMMENT '消费方用户',
`source_phone` varchar(50) COMMENT '消费方用户',
`one_user_id` bigint(20) COMMENT '分销方',
`one_usercode` varchar(20) COMMENT '分销方',
`one_phone` varchar(50) COMMENT '分销方',
`one_rate` decimal(8, 2) COMMENT '分销方提成比例',
`one_points` bigint(20) COMMENT '分销方积分',
`status` tinyint default 0 comment '状态 -1-无须分销 0-待分销 1-已分销',
`source_type` varchar(20) comment '来源',
`source_id` varchar(20) comment '来源ID',
`remark` varchar(255) comment '备注',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_date` (`source_user_id`) USING BTREE
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
ROW_FORMAT = DYNAMIC COMMENT ='用户积分分销';
-- 菜单 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible,
status, perms, icon, create_by, create_time, update_by, update_time, remark)
values (1996050872055914497, '用户积分分销', '1741377069687037954', '1', 'pointRecordLog', 'cai/pointRecordLog/index',
1, 0, 'C', '0', '0', 'cai:pointRecordLog:list', '#', 'admin', sysdate(), '', null, '用户积分分销菜单');
-- 按钮 SQL
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible,
status, perms, icon, create_by, create_time, update_by, update_time, remark)
values (1996050872055914498, '用户积分分销查询', 1996050872055914497, '1', '#', '', 1, 0, 'F', '0', '0',
'cai:pointRecordLog:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible,
status, perms, icon, create_by, create_time, update_by, update_time, remark)
values (1996050872055914500, '用户积分分销修改', 1996050872055914497, '3', '#', '', 1, 0, 'F', '0', '0',
'cai:pointRecordLog:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible,
status, perms, icon, create_by, create_time, update_by, update_time, remark)
values (1996050872055914501, '用户积分分销删除', 1996050872055914497, '4', '#', '', 1, 0, 'F', '0', '0',
'cai:pointRecordLog:remove', '#', 'admin', sysdate(), '', null, '');

View File

@@ -3,10 +3,12 @@ package com.ruoyi.web.controller.cai.admin;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cai.domain.Account; import com.ruoyi.cai.domain.Account;
import com.ruoyi.cai.dto.AddPointAdminDto;
import com.ruoyi.cai.dto.AddRechargeOrderAdminDto; import com.ruoyi.cai.dto.AddRechargeOrderAdminDto;
import com.ruoyi.cai.dto.admin.vo.AccountAdminVo; import com.ruoyi.cai.dto.admin.vo.AccountAdminVo;
import com.ruoyi.cai.manager.ConsumerManager; import com.ruoyi.cai.manager.ConsumerManager;
import com.ruoyi.cai.service.AccountService; import com.ruoyi.cai.service.AccountService;
import com.ruoyi.cai.service.PointRecordLogService;
import com.ruoyi.cai.service.RechargeOrderService; import com.ruoyi.cai.service.RechargeOrderService;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.annotation.RepeatSubmit;
@@ -14,7 +16,6 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -71,4 +72,16 @@ public class AccountController extends BaseController {
consumerManager.rechargeOrderSuccessAdmin(bo); consumerManager.rechargeOrderSuccessAdmin(bo);
return R.ok(); return R.ok();
} }
@Autowired
private PointRecordLogService pointRecordLogService;
@SaCheckPermission("cai:account:add")
@Log(title = "用户积分调账", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/updatePoint")
public R<Void> adminUpdatePoint(@RequestBody AddPointAdminDto bo) {
pointRecordLogService.adminUpdatePoint(bo);
return R.ok();
}
} }

View File

@@ -353,6 +353,7 @@ public class CaiLoginManager {
userInfo.setGuardIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_GUARD_INCOME_RATE)); userInfo.setGuardIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_GUARD_INCOME_RATE));
userInfo.setGiftIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_GIFT_INCOME_RATE)); userInfo.setGiftIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_GIFT_INCOME_RATE));
userInfo.setPayIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_PAY_INCOME_RATE)); userInfo.setPayIncomeRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_PAY_INCOME_RATE));
userInfo.setPointRate(systemConfigManager.getSystemConfigOfBigDecimal(SystemConfigEnum.DEFAULT_PAY_POINT_RATE));
userInfo.setLoginCount(1); userInfo.setLoginCount(1);
userInfo.setLastLoginIp(clientIP); userInfo.setLastLoginIp(clientIP);
userInfo.setLastLoginTime(LocalDateTime.now()); userInfo.setLastLoginTime(LocalDateTime.now());

View File

@@ -0,0 +1,96 @@
package com.ruoyi.cai.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.cai.domain.PointRecordLog;
import com.ruoyi.cai.service.PointRecordLogService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
/**
* 用户积分分销
*
* @author 77
* @date 2025-12-03
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cai/pointRecordLog")
public class PointRecordLogController extends BaseController {
private final PointRecordLogService pointRecordLogService;
/**
* 查询用户积分分销列表
*/
@SaCheckPermission("cai:pointRecordLog:list")
@GetMapping("/list")
public TableDataInfo<PointRecordLog> list(PointRecordLog bo, PageQuery pageQuery) {
Page<PointRecordLog> page = pointRecordLogService.page(pageQuery.build(), Wrappers.lambdaQuery(bo).orderByDesc(PointRecordLog::getCreateTime));
return TableDataInfo.build(page);
}
/**
* 获取用户积分分销详细信息
*
* @param id 主键
*/
@SaCheckPermission("cai:pointRecordLog:query")
@GetMapping("/{id}")
public R<PointRecordLog> getInfo(@NotNull(message = "主键不能为空")
@PathVariable String id) {
return R.ok(pointRecordLogService.getById(id));
}
/**
* 新增用户积分分销
*/
@SaCheckPermission("cai:pointRecordLog:add")
@Log(title = "用户积分分销", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody PointRecordLog bo) {
return toAjax(pointRecordLogService.save(bo));
}
/**
* 修改用户积分分销
*/
@SaCheckPermission("cai:pointRecordLog:edit")
@Log(title = "用户积分分销", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody PointRecordLog bo) {
return toAjax(pointRecordLogService.updateById(bo));
}
/**
* 删除用户积分分销
*
* @param ids 主键串
*/
@SaCheckPermission("cai:pointRecordLog:remove")
@Log(title = "用户积分分销", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable String[] ids) {
return toAjax(pointRecordLogService.removeBatchByIds(Arrays.asList(ids), true));
}
}

View File

@@ -0,0 +1,83 @@
package com.ruoyi.cai.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 用户积分分销对象 cai_point_record_log
*
* @author 77
* @date 2025-12-03
*/
@Data
@TableName("cai_point_record_log")
public class PointRecordLog implements Serializable{
private static final long serialVersionUID=1L;
/**
*
*/
@TableId(value = "id",type = IdType.AUTO)
private Long id;
/**
* 积分
*/
private Long points;
/**
* 消费方用户
*/
private Long sourceUserId;
/**
* 消费方用户
*/
private String sourceUsercode;
/**
* 消费方用户
*/
private String sourcePhone;
/**
* 分销方
*/
private Long oneUserId;
/**
* 分销方
*/
private String oneUsercode;
/**
* 分销方
*/
private String onePhone;
/**
* 分销方提成比例
*/
private BigDecimal oneRate;
/**
* 分销方积分
*/
private Long onePoints;
/**
* 状态 -1-无须分销 0-待分销 1-已分销
*/
private Integer status;
/**
* 来源
*/
private String sourceType;
/**
* 来源ID
*/
private String sourceId;
/**
* 备注
*/
private String remark;
private LocalDateTime createTime;
}

View File

@@ -48,6 +48,8 @@ public class RechargeOrder implements Serializable {
* 1-充值余额 2-充值收益 * 1-充值余额 2-充值收益
*/ */
private Integer rechargeType; private Integer rechargeType;
private Long givePoint;
/** /**
* 价格 * 价格
*/ */

View File

@@ -41,6 +41,9 @@ public class UserInfo {
* 奖励好友充值的比率 * 奖励好友充值的比率
*/ */
private BigDecimal payIncomeRate; private BigDecimal payIncomeRate;
/**
*/
private BigDecimal pointRate;
/** /**
* 登录次数 * 登录次数
*/ */

View File

@@ -0,0 +1,25 @@
package com.ruoyi.cai.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class AddPointAdminDto implements Serializable {
/**
* 员工ID
*/
private String usercode;
/**
* 调整的金额
*/
private Long point;
/**
* 是否参与分销
*/
private boolean distribution;
private String remark;
}

View File

@@ -19,6 +19,7 @@ public class RechargeConsumerResp {
private Long rechargeCoin; private Long rechargeCoin;
private Long userId; private Long userId;
private Long consumeLogId; private Long consumeLogId;
private Long pointLogId;
private Long traceId; private Long traceId;
private boolean success; private boolean success;
} }

View File

@@ -8,12 +8,18 @@ import lombok.Getter;
*/ */
@Getter @Getter
public enum ConsumeLogStatus { public enum ConsumeLogStatus {
NO(-1), NO(-1,"无需分销"),
READY(0), READY(0,"待分销"),
ALREADY(1); ALREADY(1, "已分销");
private final Integer code; private final Integer code;
private String text;
ConsumeLogStatus(Integer code) { ConsumeLogStatus(Integer code) {
this.code = code; this.code = code;
} }
ConsumeLogStatus(Integer code, String text) {
this.code = code;
this.text = text;
}
} }

View File

@@ -0,0 +1,14 @@
package com.ruoyi.cai.enums;
import lombok.Getter;
@Getter
public enum PointLogType {
ORDER("充值触发"),
ADMIN("系统调整");
private String code;
PointLogType(String code) {
this.code = code;
}
}

View File

@@ -69,6 +69,7 @@ public enum SystemConfigEnum {
DEFAULT_GIFT_INCOME_RATE("0.07", "默认分销上级礼物提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), DEFAULT_GIFT_INCOME_RATE("0.07", "默认分销上级礼物提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
DEFAULT_GUARD_INCOME_RATE("0.07", "默认分销上级守护提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), DEFAULT_GUARD_INCOME_RATE("0.07", "默认分销上级守护提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
DEFAULT_PAY_INCOME_RATE("0.3", "默认分销上级充值提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), DEFAULT_PAY_INCOME_RATE("0.3", "默认分销上级充值提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
DEFAULT_PAY_POINT_RATE("0.07", "默认分销上级充值的积分提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
PAY_INCOME_RATE("0", "分销上级充值提成配置大于0数据后将强制使用该提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()), PAY_INCOME_RATE("0", "分销上级充值提成配置大于0数据后将强制使用该提成",SystemConfigGroupEnum.BUSINESS,new RateSystemConfigCheck()),
// @Deprecated // @Deprecated
// DEFAULT_UNION_GIFT_INCOME_RATE("0.01", "默认工会礼物提成",SystemConfigGroupEnum.BUSINESS, new RateSystemConfigCheck()), // DEFAULT_UNION_GIFT_INCOME_RATE("0.01", "默认工会礼物提成",SystemConfigGroupEnum.BUSINESS, new RateSystemConfigCheck()),

View File

@@ -180,6 +180,9 @@ public class ConsumerManager {
return resp; return resp;
} }
@Autowired
private PointRecordLogService pointRecordLogService;
public RechargeConsumerResp rechargeOrderSuccess(String tradeNo, Map<String,String> params, String appId, PayTypeEnum payTypeEnum){ public RechargeConsumerResp rechargeOrderSuccess(String tradeNo, Map<String,String> params, String appId, PayTypeEnum payTypeEnum){
RechargeConsumerResp resp = rechargeOrderService.orderSuccess(tradeNo,params,appId,payTypeEnum); RechargeConsumerResp resp = rechargeOrderService.orderSuccess(tradeNo,params,appId,payTypeEnum);
if(resp.isSuccess()){ if(resp.isSuccess()){
@@ -198,6 +201,11 @@ public class ConsumerManager {
}catch (Exception e){ }catch (Exception e){
log.error("RabbitMq 发送失败, 充值分销流程流转失败!",e); log.error("RabbitMq 发送失败, 充值分销流程流转失败!",e);
} }
try {
pointRecordLogService.dealCalculateSales(resp.getPointLogId());
}catch (Exception e){
log.error("充值积分分销失败",e);
}
try { try {
// 记录用户的消费金额统计 // 记录用户的消费金额统计
accountTotalManager.incsPayIncomeCoin(resp.getUserId(), resp.getRechargeCoin(),resp.getPrice(), resp.getConsumeLogId()); accountTotalManager.incsPayIncomeCoin(resp.getUserId(), resp.getRechargeCoin(),resp.getPrice(), resp.getConsumeLogId());

View File

@@ -43,4 +43,8 @@ public interface AccountMapper extends BaseMapper<Account> {
void incsTrdPayTotal(@Param("userId") Long userId, @Param("price") BigDecimal price); void incsTrdPayTotal(@Param("userId") Long userId, @Param("price") BigDecimal price);
List<RankNodeRecharge> rankTotalPay(@Param("limit") int limit); List<RankNodeRecharge> rankTotalPay(@Param("limit") int limit);
void incrPoint(@Param("userId") Long userId, @Param("point") Long point);
boolean decrPoint(@Param("userId") Long userId, @Param("point") Long point);
} }

View File

@@ -0,0 +1,14 @@
package com.ruoyi.cai.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.cai.domain.PointRecordLog;
/**
* 用户积分分销Mapper接口
*
* @author 77
* @date 2025-12-03
*/
public interface PointRecordLogMapper extends BaseMapper<PointRecordLog> {
}

View File

@@ -2,10 +2,7 @@ package com.ruoyi.cai.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.cai.domain.Account; import com.ruoyi.cai.domain.*;
import com.ruoyi.cai.domain.ConsumeLog;
import com.ruoyi.cai.domain.Gift;
import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.dto.admin.vo.AccountAdminVo; import com.ruoyi.cai.dto.admin.vo.AccountAdminVo;
import com.ruoyi.cai.dto.video.VideoSettleResp; import com.ruoyi.cai.dto.video.VideoSettleResp;
import com.ruoyi.cai.dto.video.WithholdingFeeUserResp; import com.ruoyi.cai.dto.video.WithholdingFeeUserResp;
@@ -34,6 +31,8 @@ public interface AccountService extends IService<Account> {
void withdrawFail(Long userId, Long incomeCoin, Long traceId); void withdrawFail(Long userId, Long incomeCoin, Long traceId);
PointRecordLog rechargePoint(RechargeOrder rechargeOrder, User user);
void recharge(ConsumeLog consumeLog); void recharge(ConsumeLog consumeLog);
void rechargeAdminIgnoreAccount(ConsumeLog consumeLog); void rechargeAdminIgnoreAccount(ConsumeLog consumeLog);

View File

@@ -0,0 +1,22 @@
package com.ruoyi.cai.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.cai.domain.PointRecordLog;
import com.ruoyi.cai.domain.RechargeOrder;
import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.dto.AddPointAdminDto;
/**
* 用户积分分销Service接口
*
* @author 77
* @date 2025-12-03
*/
public interface PointRecordLogService extends IService<PointRecordLog> {
void adminUpdatePoint(AddPointAdminDto dto);
PointRecordLog initOrder(RechargeOrder order, User user);
void dealCalculateSales(Long pointLogId);
}

View File

@@ -9,7 +9,9 @@ import com.ruoyi.cai.domain.*;
import com.ruoyi.cai.dto.admin.vo.AccountAdminVo; import com.ruoyi.cai.dto.admin.vo.AccountAdminVo;
import com.ruoyi.cai.dto.video.VideoSettleResp; import com.ruoyi.cai.dto.video.VideoSettleResp;
import com.ruoyi.cai.dto.video.WithholdingFeeUserResp; import com.ruoyi.cai.dto.video.WithholdingFeeUserResp;
import com.ruoyi.cai.enums.ConsumeLogStatus;
import com.ruoyi.cai.enums.ConsumeLogType; import com.ruoyi.cai.enums.ConsumeLogType;
import com.ruoyi.cai.enums.PointLogType;
import com.ruoyi.cai.enums.SystemConfigEnum; import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.enums.account.AccountChangeCodeEnum; import com.ruoyi.cai.enums.account.AccountChangeCodeEnum;
import com.ruoyi.cai.enums.account.AccountTypeEnum; import com.ruoyi.cai.enums.account.AccountTypeEnum;
@@ -33,6 +35,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
/** /**
* 用户账户Service业务层处理 * 用户账户Service业务层处理
@@ -214,6 +217,21 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
accountChangeLogService.saveLogNoAdmin(user.getId(),user.getUsercode(), AccountChangeCodeEnum.WITHDRAW_FAIL,incomeCoin,traceId); accountChangeLogService.saveLogNoAdmin(user.getId(),user.getUsercode(), AccountChangeCodeEnum.WITHDRAW_FAIL,incomeCoin,traceId);
} }
@Autowired
private PointRecordLogService pointRecordLogService;
@Transactional(rollbackFor = Exception.class)
@Override
public PointRecordLog rechargePoint(RechargeOrder rechargeOrder, User user){
if(rechargeOrder.getGivePoint() == null || rechargeOrder.getGivePoint() == 0){
return null;
}
log.info("开始赠送积分 orderNo={}", rechargeOrder.getOrderNo());
baseMapper.incrPoint(rechargeOrder.getUserId(), rechargeOrder.getGivePoint());
PointRecordLog pointRecordLog = pointRecordLogService.initOrder(rechargeOrder, user);
return pointRecordLog;
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void recharge(ConsumeLog consumeLog){ public void recharge(ConsumeLog consumeLog){

View File

@@ -0,0 +1,137 @@
package com.ruoyi.cai.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.*;
import com.ruoyi.cai.dto.AddPointAdminDto;
import com.ruoyi.cai.enums.ConsumeLogStatus;
import com.ruoyi.cai.enums.PointLogType;
import com.ruoyi.cai.mapper.AccountMapper;
import com.ruoyi.cai.mapper.PointRecordLogMapper;
import com.ruoyi.cai.service.PointRecordLogService;
import com.ruoyi.cai.service.UserInfoService;
import com.ruoyi.cai.service.UserInviteService;
import com.ruoyi.cai.service.UserService;
import com.ruoyi.cai.util.CaiNumUtil;
import com.ruoyi.common.exception.ServiceException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/**
* 用户积分分销Service业务层处理
*
* @author 77
* @date 2025-12-03
*/
@RequiredArgsConstructor
@Service
public class PointRecordLogServiceImpl extends ServiceImpl<PointRecordLogMapper,PointRecordLog> implements PointRecordLogService {
@Autowired
private UserInviteService userInviteService;
@Autowired
private UserService userService;
@Autowired
private UserInfoService userInfoService;
@Resource
private AccountMapper accountMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void adminUpdatePoint(AddPointAdminDto dto){
String usercode = dto.getUsercode();
User user = userService.getByUserCode(usercode);
if(user == null){
throw new ServiceException("用户不存在");
}
if(dto.isDistribution()){
if(dto.getPoint() <= 0){
throw new ServiceException("开启分销情况下,无法调整积分为负数");
}
}
accountMapper.incrPoint(user.getId(), dto.getPoint());
PointRecordLog pointLog = new PointRecordLog();
pointLog.setPoints(dto.getPoint());
pointLog.setSourceUserId(user.getId());
pointLog.setSourceUsercode(user.getUsercode());
pointLog.setSourcePhone(user.getMobile());
UserInvite userInvite = userInviteService.getByUserId(user.getId());
if(userInvite != null){
User oneUser = userService.getById(userInvite.getInviteId());
if(oneUser != null && oneUser.getStatus() == 0){
UserInfo userInfo = userInfoService.getByUserId(userInvite.getUserId());
pointLog.setOneRate(userInfo.getPointRate());
pointLog.setOneUserId(oneUser.getId());
pointLog.setOneUsercode(oneUser.getUsercode());
pointLog.setOnePhone(oneUser.getMobile());
pointLog.setOnePoints(CaiNumUtil.coin(pointLog.getPoints(),pointLog.getOneRate()));
}
}
if(dto.isDistribution()){ // 需要分销,直接分销
pointLog.setStatus(ConsumeLogStatus.ALREADY.getCode());
if(pointLog.getOnePoints() >= 0 && pointLog.getOneUserId() != null){
accountMapper.incrPoint(pointLog.getOneUserId(), pointLog.getOnePoints());
}
}else{
pointLog.setStatus(ConsumeLogStatus.NO.getCode());
}
pointLog.setSourceType(PointLogType.ADMIN.getCode());
pointLog.setRemark(dto.getRemark());
pointLog.setCreateTime(LocalDateTime.now());
this.save(pointLog);
}
@Override
public PointRecordLog initOrder(RechargeOrder rechargeOrder, User user){
PointRecordLog log = new PointRecordLog();
log.setPoints(rechargeOrder.getGivePoint());
log.setSourceUserId(user.getId());
log.setSourceUsercode(user.getUsercode());
log.setSourcePhone(user.getMobile());
UserInvite userInvite = userInviteService.getByUserId(user.getId());
if(userInvite != null){
User oneUser = userService.getById(userInvite.getInviteId());
if(oneUser != null && oneUser.getStatus() == 0){
UserInfo userInfo = userInfoService.getByUserId(userInvite.getUserId());
log.setOneRate(userInfo.getPointRate());
log.setOneUserId(oneUser.getId());
log.setOneUsercode(oneUser.getUsercode());
log.setOnePhone(oneUser.getMobile());
log.setOnePoints(CaiNumUtil.coin(log.getPoints(),log.getOneRate()));
}
}
log.setStatus(ConsumeLogStatus.READY.getCode());
log.setSourceType(PointLogType.ORDER.getCode());
log.setSourceId(rechargeOrder.getOrderNo());
log.setCreateTime(LocalDateTime.now());
this.save(log);
return log;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void dealCalculateSales(Long pointLogId) {
PointRecordLog pointRecordLog = this.getById(pointLogId);
if(pointRecordLog == null){
return;
}
if(!ConsumeLogStatus.READY.getCode().equals(pointRecordLog.getStatus())){
return;
}
boolean update = this.update(Wrappers.lambdaUpdate(PointRecordLog.class)
.eq(PointRecordLog::getId, pointLogId)
.eq(PointRecordLog::getStatus, ConsumeLogStatus.READY.getCode())
.set(PointRecordLog::getStatus, ConsumeLogStatus.ALREADY.getCode()));
if(!update){
return;
}
if(pointRecordLog.getOneUserId() == null || pointRecordLog.getPoints() <= 0){
return;
}
accountMapper.incrPoint(pointRecordLog.getOneUserId(), pointRecordLog.getOnePoints());
}
}

View File

@@ -127,9 +127,13 @@ public class RechargeOrderServiceImpl extends ServiceImpl<RechargeOrderMapper,Re
consumeLog.setType(ConsumeLogType.RECHARGE.getCode()); consumeLog.setType(ConsumeLogType.RECHARGE.getCode());
consumeLog.setAmount(rechargeOrder.getRechargeCoin()); consumeLog.setAmount(rechargeOrder.getRechargeCoin());
accountService.recharge(consumeLog); accountService.recharge(consumeLog);
PointRecordLog pointRecordLog = accountService.rechargePoint(rechargeOrder, user);
RechargeConsumerResp resp = new RechargeConsumerResp(); RechargeConsumerResp resp = new RechargeConsumerResp();
resp.setSuccess(true); resp.setSuccess(true);
resp.setConsumeLogId(consumeLog.getId()); resp.setConsumeLogId(consumeLog.getId());
if(pointRecordLog != null){
resp.setPointLogId(pointRecordLog.getId());
}
resp.setUserId(user.getId()); resp.setUserId(user.getId());
resp.setUser(user); resp.setUser(user);
resp.setTraceId(traceId); resp.setTraceId(traceId);

View File

@@ -98,4 +98,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by t1.total_buy_coin desc order by t1.total_buy_coin desc
limit #{limit} limit #{limit}
</select> </select>
<update id="incrPoint">
update cai_account
set points = points + #{point}
where user_id = #{userId}
</update>
<update id="decrPoint">
update cai_account
set points = points - #{point}
where user_id = #{userId} and (points - #{point}) >= 0
</update>
</mapper> </mapper>

View File

@@ -0,0 +1,27 @@
<?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.cai.mapper.PointRecordLogMapper">
<resultMap type="com.ruoyi.cai.domain.PointRecordLog" id="PointRecordLogResult">
<result property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="points" column="points"/>
<result property="sourceUserId" column="source_user_id"/>
<result property="sourceUsercode" column="source_usercode"/>
<result property="sourcePhone" column="source_phone"/>
<result property="oneUserId" column="one_user_id"/>
<result property="oneUsercode" column="one_usercode"/>
<result property="onePhone" column="one_phone"/>
<result property="oneRate" column="one_rate"/>
<result property="onePoints" column="one_points"/>
<result property="status" column="status"/>
<result property="sourceType" column="source_type"/>
<result property="sourceId" column="source_id"/>
<result property="remark" column="remark"/>
<result property="createTime" column="create_time"/>
</resultMap>
</mapper>