This commit is contained in:
张良(004796)
2024-01-12 17:50:50 +08:00
parent 728192d4f0
commit 28623f17d1
28 changed files with 746 additions and 110 deletions

View File

@@ -6,10 +6,12 @@ import com.ruoyi.cai.domain.Account;
import com.ruoyi.cai.domain.ConsumeLog;
import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.dto.admin.vo.AccountAdminVo;
import com.ruoyi.cai.dto.video.VideoSettleResp;
import com.ruoyi.cai.dto.video.WithholdingFeeUserResp;
import com.ruoyi.cai.enums.AccountBusinessEnum;
import com.ruoyi.cai.enums.AccountChangeEnum;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.common.core.domain.PageQuery;
import org.springframework.transaction.annotation.Transactional;
/**
* 用户账户Service接口
@@ -32,4 +34,8 @@ public interface AccountService extends IService<Account> {
Page<AccountAdminVo> pageAdmin(PageQuery pageQuery, AccountAdminVo bo);
void distribution(Long userId, Long amount, AccountChangeEnum oneEnum,Long traceId);
WithholdingFeeUserResp withholdingFeeUser(Long userId, Long price);
VideoSettleResp videoSettle(Room room);
}

View File

@@ -1,13 +1,17 @@
package com.ruoyi.cai.service.impl;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.cai.domain.*;
import com.ruoyi.cai.dto.admin.vo.AccountAdminVo;
import com.ruoyi.cai.dto.video.VideoSettleResp;
import com.ruoyi.cai.dto.video.WithholdingFeeUserResp;
import com.ruoyi.cai.enums.AccountBusinessEnum;
import com.ruoyi.cai.enums.AccountChangeEnum;
import com.ruoyi.cai.enums.ConsumeLogType;
import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.manager.IdManager;
import com.ruoyi.cai.manager.SystemConfigManager;
@@ -15,15 +19,19 @@ import com.ruoyi.cai.mapper.AccountMapper;
import com.ruoyi.cai.pay.RechargeTypeEnum;
import com.ruoyi.cai.service.*;
import com.ruoyi.cai.util.NumCaUtil;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.bean.RoomData;
import com.ruoyi.cai.ws.bean.UserData;
import com.ruoyi.cai.ws.cache.RoomDataCache;
import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.xml.transform.Source;
import java.math.BigDecimal;
/**
@@ -127,7 +135,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
coin = -account.getCoin();
incomeCoin = diff;
boolean decrCoin = baseMapper.decrCoin(fromUserId, -coin);
boolean decrIncomeCoin = baseMapper.decrIncomeCoin(fromUserId, -diff);
boolean decrIncomeCoin = baseMapper.decrIncomeCoin(fromUserId, -incomeCoin);
if(decrCoin && decrIncomeCoin){
flag = true;
}
@@ -216,4 +224,147 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
accountChangeLogService.saveLogNoAdmin(userId,user.getUsercode(), RechargeTypeEnum.COIN_INCOME,accountChangeEnum,amount,traceId);
}
/**
* 视频-预付款
* @param userId
* @param price
*/
@Override
@Transactional(rollbackFor = Exception.class)
public WithholdingFeeUserResp withholdingFeeUser(Long userId, Long price) {
Account account = this.getByUserId(userId);
if(account == null){
throw new ServiceException("账户异常");
}
long totalCoin = account.getIncomeCoin() + account.getCoin();
if(totalCoin < price){
throw new ServiceException("余额不足");
}
boolean flag = false;
long coin = -price; // 消费余额
long incomeCoin = 0; // 消费收益
long diff = account.getCoin() - price;
// 充值币够用
if(diff > 0){
flag = baseMapper.decrCoin(userId, -coin);
} else { // 充值币不够用
coin = -account.getCoin();
incomeCoin = diff;
boolean decrCoin = baseMapper.decrCoin(userId, -coin);
boolean decrIncomeCoin = baseMapper.decrIncomeCoin(userId, -incomeCoin);
if(decrCoin && decrIncomeCoin){
flag = true;
}
}
// 扣费不成功
if(!flag){
throw new ServiceException("扣费失败");
}
WithholdingFeeUserResp resp = new WithholdingFeeUserResp();
resp.setDecrCoin(-coin);
resp.setDecrIncomeCoin(-incomeCoin);
return resp;
}
@Autowired
private RoomService roomService;
@Autowired
private UserCallService userCallService;
@Override
public VideoSettleResp videoSettle(Room room) {
RoomData roomData = room.getRoomData();
UserCall userCall = userCallService.getById(roomData.getRoomId());
UserData callUserData = room.getCallUserData();
Long callPrice = roomData.getCallPrice();
Long callTime = roomService.getCallTime(room);
// 本次支付金额
long totalAmount = callPrice * (callTime / 60); // 本次需要支付的金额
Long payCoin = roomData.getPayCoin(); // 已经支付的余额
Long payIncome = roomData.getPayIncome(); // 已经支付的收益
// 补差价
long diff = totalAmount - (payCoin + payIncome);
Account callAccount = this.getByUserId(callUserData.getId());
long userAmount = callAccount.getCoin() + callAccount.getIncomeCoin(); // 用户余额
if(diff > 0){
// 账户上面有余额
if(userAmount > 0){
diff = Math.min(userAmount, diff);
log.info("roomid {} 已支付 {} 仍需要补差价:{}, 用户余额:{} ",
roomData.getRoomId(),roomData.getPayCoin() + roomData.getPayIncome(),diff, userAmount);
WithholdingFeeUserResp resp = withholdingFeeUser(callUserData.getId(), diff);
payCoin = payCoin + resp.getDecrCoin();
payIncome = payIncome + resp.getDecrIncomeCoin();
} else {
log.info("房间需要补差价,但用户余额不足 roomid {} 已支付 {} 仍需要补差价:{}", roomData.getRoomId(),roomData.getPayCoin() + roomData.getPayIncome(),diff);
}
}else{
// 退钱逻辑
long incsCoin = 0L; // 需要退的金额
long incsIncomeCoin = 0L; // 需要退的收益金额
diff = Math.abs(diff); // 待退款的钱
if(roomData.getPayCoin() > diff){ // 消费的金额大于待退款金额
incsCoin = diff;
}else {
if(roomData.getPayIncome() > (diff - roomData.getPayCoin())){ // 消费金额不够退,但是收益金额扣扣费
incsCoin = roomData.getPayCoin();
incsIncomeCoin = roomData.getPayIncome() - (diff - roomData.getPayCoin());
} else { // 消费金额不够退 余额也不够退 能退多少是多少
incsCoin = roomData.getPayCoin();
incsIncomeCoin = roomData.getPayIncome();
}
}
if(incsCoin > 0){
payCoin = payCoin - incsCoin;
baseMapper.incsCoin(callUserData.getId(), incsCoin);
}
if(incsIncomeCoin > 0){
payIncome = payIncome - incsIncomeCoin;
baseMapper.incsCoin(callUserData.getId(), incsIncomeCoin);
}
}
Long amountReal = payCoin + payIncome; // 实际支付的金额
Long anchorAmount = NumCaUtil.coin(amountReal,roomData.getVideoDivide());
User fromUser = userService.getById(userCall.getFromUid());
User toUser = userService.getById(userCall.getToUid());
baseMapper.incsIncomeCoin(toUser.getId(),anchorAmount);
Long tractId = IdManager.nextId();
// 记录消费方的流水
if(payCoin != 0){
accountChangeLogService.saveLogNoAdmin(fromUser.getId(),fromUser.getUsercode(), RechargeTypeEnum.COIN, AccountChangeEnum.USER_VIDEO, payCoin, tractId);
}
if(payIncome != 0){
accountChangeLogService.saveLogNoAdmin(fromUser.getId(),fromUser.getUsercode(), RechargeTypeEnum.COIN_INCOME,AccountChangeEnum.USER_VIDEO,payIncome,tractId);
}
// 记录接收方的流水
if(anchorAmount != 0){
accountChangeLogService.saveLogNoAdmin(toUser.getId(),toUser.getUsercode(), RechargeTypeEnum.COIN_INCOME,AccountChangeEnum.ANCHOR_VIDEO,anchorAmount,tractId);
}
ConsumeLog consumeLog = new ConsumeLog();
consumeLog.init(fromUser,toUser);
consumeLog.setType(ConsumeLogType.VIDEO.getCode());
consumeLog.setBusinessEnum(AccountBusinessEnum.VIDEO.name());
consumeLog.setTraceId(tractId);
consumeLog.setTargetRate(roomData.getVideoDivide());
consumeLog.setAmount(amountReal);
consumeLog.setAnchorAmount(anchorAmount);
// 获取分销的比例和用户
consumeLogService.calculateInitFenxiao(consumeLog);
consumeLogService.save(consumeLog);
userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
.eq(UserCall::getId, userCall.getId())
.set(UserCall::getBeginTime, DateUtil.date(roomData.getBeginTime()).toLocalDateTime())
.set(UserCall::getEndTime,DateUtil.date(roomData.getHangUpTime()).toLocalDateTime())
.set(UserCall::getCallTime,roomData.getHangUpTime() - roomData.getBeginTime())
.set(UserCall::getCallAmount,amountReal)
.set(UserCall::getCallIncome, anchorAmount)
.set(UserCall::getStatus, RoomStatusEnums.STATUS_HANGUP.getCode()));
VideoSettleResp resp = new VideoSettleResp();
resp.setConsumeLog(consumeLog);
resp.setPayIncome(payIncome);
resp.setPayCoin(payCoin);
return resp;
}
}