|
|
@@ -0,0 +1,188 @@
|
|
|
+package com.etotem.cfc.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.etotem.cfc.entity.PlatformBalanceLog;
|
|
|
+import com.etotem.cfc.entity.UserPlatformBalance;
|
|
|
+import com.etotem.cfc.mapper.PlatformBalanceLogMapper;
|
|
|
+import com.etotem.cfc.mapper.UserPlatformBalanceMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class PlatformPointsService {
|
|
|
+
|
|
|
+ private static final String TYPE_EARN = "earn";
|
|
|
+ private static final String TYPE_SPEND = "spend";
|
|
|
+ private static final String TYPE_FREEZE = "freeze";
|
|
|
+ private static final String TYPE_UNFREEZE = "unfreeze";
|
|
|
+ private static final String TYPE_WITHDRAW = "withdraw";
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private UserPlatformBalanceMapper balanceMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private PlatformBalanceLogMapper logMapper;
|
|
|
+
|
|
|
+ /** 获取或创建用户的 CF 值余额记录 */
|
|
|
+ private UserPlatformBalance getOrCreate(Long userId) {
|
|
|
+ UserPlatformBalance balance = balanceMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<UserPlatformBalance>()
|
|
|
+ .eq(UserPlatformBalance::getUserId, userId));
|
|
|
+ if (balance == null) {
|
|
|
+ balance = new UserPlatformBalance();
|
|
|
+ balance.setUserId(userId);
|
|
|
+ balance.setTotalEarned(0);
|
|
|
+ balance.setAvailable(0);
|
|
|
+ balance.setFrozen(0);
|
|
|
+ balance.setWithdrawn(0);
|
|
|
+ balance.setExchanged(0);
|
|
|
+ balance.setCreatedAt(new Date());
|
|
|
+ balance.setUpdatedAt(new Date());
|
|
|
+ balanceMapper.insert(balance);
|
|
|
+ }
|
|
|
+ return balance;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int safeInt(Integer v) {
|
|
|
+ return v == null ? 0 : v;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeLog(Long userId, Long familyId, String type, int amount,
|
|
|
+ int balanceAfter, String refType, Long refId, String remark) {
|
|
|
+ PlatformBalanceLog log = new PlatformBalanceLog();
|
|
|
+ log.setUserId(userId);
|
|
|
+ log.setFamilyId(familyId);
|
|
|
+ log.setType(type);
|
|
|
+ log.setAmount(amount);
|
|
|
+ log.setBalanceAfter(balanceAfter);
|
|
|
+ log.setRefType(refType);
|
|
|
+ log.setRefId(refId);
|
|
|
+ log.setRemark(remark);
|
|
|
+ log.setCreatedAt(new Date());
|
|
|
+ logMapper.insert(log);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 用户获得 CF 值 */
|
|
|
+ @Transactional
|
|
|
+ public void earn(Long userId, int amount, String refType, Long refId, String remark) {
|
|
|
+ if (amount <= 0) {
|
|
|
+ throw new IllegalArgumentException("CF值数量必须为正数");
|
|
|
+ }
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ b.setTotalEarned(safeInt(b.getTotalEarned()) + amount);
|
|
|
+ b.setAvailable(safeInt(b.getAvailable()) + amount);
|
|
|
+ b.setUpdatedAt(new Date());
|
|
|
+ balanceMapper.updateById(b);
|
|
|
+ writeLog(userId, b.getFamilyId(), TYPE_EARN, amount, safeInt(b.getAvailable()),
|
|
|
+ refType, refId, remark);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 消费可用 CF 值(兑换等),余额不足抛异常 */
|
|
|
+ @Transactional
|
|
|
+ public void spend(Long userId, int amount, String refType, Long refId, String remark) {
|
|
|
+ if (amount <= 0) {
|
|
|
+ throw new IllegalArgumentException("CF值数量必须为正数");
|
|
|
+ }
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ int available = safeInt(b.getAvailable());
|
|
|
+ if (available < amount) {
|
|
|
+ throw new RuntimeException("CF值余额不足");
|
|
|
+ }
|
|
|
+ b.setAvailable(available - amount);
|
|
|
+ b.setExchanged(safeInt(b.getExchanged()) + amount);
|
|
|
+ b.setUpdatedAt(new Date());
|
|
|
+ balanceMapper.updateById(b);
|
|
|
+ writeLog(userId, b.getFamilyId(), TYPE_SPEND, amount, safeInt(b.getAvailable()),
|
|
|
+ refType, refId, remark);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 提现申请:可用 → 冻结 */
|
|
|
+ @Transactional
|
|
|
+ public void freeze(Long userId, int amount, Long refId) {
|
|
|
+ if (amount <= 0) {
|
|
|
+ throw new IllegalArgumentException("CF值数量必须为正数");
|
|
|
+ }
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ int available = safeInt(b.getAvailable());
|
|
|
+ if (available < amount) {
|
|
|
+ throw new RuntimeException("CF值余额不足");
|
|
|
+ }
|
|
|
+ b.setAvailable(available - amount);
|
|
|
+ b.setFrozen(safeInt(b.getFrozen()) + amount);
|
|
|
+ b.setUpdatedAt(new Date());
|
|
|
+ balanceMapper.updateById(b);
|
|
|
+ writeLog(userId, b.getFamilyId(), TYPE_FREEZE, amount, safeInt(b.getAvailable()),
|
|
|
+ "withdrawal", refId, "提现冻结");
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 提现审核拒绝:冻结 → 可用 */
|
|
|
+ @Transactional
|
|
|
+ public void unfreeze(Long userId, int amount, Long refId) {
|
|
|
+ if (amount <= 0) {
|
|
|
+ throw new IllegalArgumentException("CF值数量必须为正数");
|
|
|
+ }
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ int frozen = safeInt(b.getFrozen());
|
|
|
+ if (frozen < amount) {
|
|
|
+ throw new RuntimeException("冻结CF值不足");
|
|
|
+ }
|
|
|
+ b.setFrozen(frozen - amount);
|
|
|
+ b.setAvailable(safeInt(b.getAvailable()) + amount);
|
|
|
+ b.setUpdatedAt(new Date());
|
|
|
+ balanceMapper.updateById(b);
|
|
|
+ writeLog(userId, b.getFamilyId(), TYPE_UNFREEZE, amount, safeInt(b.getAvailable()),
|
|
|
+ "withdrawal", refId, "提现审核拒绝解冻");
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 提现审核通过:冻结 → 已提现 */
|
|
|
+ @Transactional
|
|
|
+ public void confirmWithdraw(Long userId, int amount, Long refId) {
|
|
|
+ if (amount <= 0) {
|
|
|
+ throw new IllegalArgumentException("CF值数量必须为正数");
|
|
|
+ }
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ int frozen = safeInt(b.getFrozen());
|
|
|
+ if (frozen < amount) {
|
|
|
+ throw new RuntimeException("冻结CF值不足");
|
|
|
+ }
|
|
|
+ b.setFrozen(frozen - amount);
|
|
|
+ b.setWithdrawn(safeInt(b.getWithdrawn()) + amount);
|
|
|
+ b.setUpdatedAt(new Date());
|
|
|
+ balanceMapper.updateById(b);
|
|
|
+ writeLog(userId, b.getFamilyId(), TYPE_WITHDRAW, amount, safeInt(b.getAvailable()),
|
|
|
+ "withdrawal", refId, "提现成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 查询用户 CF 值余额 */
|
|
|
+ public Map<String, Object> getBalance(Long userId) {
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ Map<String, Object> result = new HashMap<>();
|
|
|
+ result.put("available", safeInt(b.getAvailable()));
|
|
|
+ result.put("frozen", safeInt(b.getFrozen()));
|
|
|
+ result.put("withdrawn", safeInt(b.getWithdrawn()));
|
|
|
+ result.put("exchanged", safeInt(b.getExchanged()));
|
|
|
+ result.put("totalEarned", safeInt(b.getTotalEarned()));
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 查询可提现余额 */
|
|
|
+ public Integer getWithdrawable(Long userId) {
|
|
|
+ UserPlatformBalance b = getOrCreate(userId);
|
|
|
+ return safeInt(b.getAvailable());
|
|
|
+ }
|
|
|
+
|
|
|
+ /** CF 值流水分页 */
|
|
|
+ public Page<PlatformBalanceLog> getLogs(Long userId, Integer page, Integer size) {
|
|
|
+ Page<PlatformBalanceLog> pageParam = new Page<>(page, size);
|
|
|
+ return logMapper.selectPage(pageParam,
|
|
|
+ new LambdaQueryWrapper<PlatformBalanceLog>()
|
|
|
+ .eq(PlatformBalanceLog::getUserId, userId)
|
|
|
+ .orderByDesc(PlatformBalanceLog::getCreatedAt));
|
|
|
+ }
|
|
|
+}
|