p-honggang.li
5 天以前 ac918503bb5e8fad007348e7e39ba7275b75f334
src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java
@@ -7,6 +7,7 @@
import com.webmanage.common.BusinessException;
import com.webmanage.common.PageResult;
import com.webmanage.dto.AddPointsFlowDTO;
import com.webmanage.dto.DeductUserPointsDTO;
import com.webmanage.dto.PointsFlowQueryDTO;
import com.webmanage.emun.RuleTypeEnum;
import com.webmanage.entity.PointsFlow;
@@ -14,6 +15,9 @@
import com.webmanage.entity.UserPoints;
import com.webmanage.mapper.PointsFlowMapper;
import com.webmanage.mapper.UserPointsMapper;
import com.webmanage.mapper.PointsTransactionMapper;
import com.webmanage.entity.PointsTransaction;
import com.webmanage.service.OrderInfoService;
import com.webmanage.service.PointsFlowService;
import com.webmanage.service.PointsRuleService;
import lombok.extern.slf4j.Slf4j;
@@ -39,6 +43,10 @@
    @Resource
    private PointsRuleService pointsRuleService;
    @Resource
    private PointsTransactionMapper pointsTransactionMapper;
    @Override
    public PageResult<PointsFlow> getPersonalPointsFlowPage(PointsFlowQueryDTO queryDTO) {
@@ -174,10 +182,10 @@
        }
        // 每日上限校验(分别校验)
        if (applyUser && userRule.getIsLimit() != null && userRule.getIsLimit() == 0) {
        if (applyUser && userRule.getIsLimit() != null && userRule.getIsLimit() == 1) {
            checkDailyLimitByRule(userId, unitId, userRule, userPointsChange);
        }
        if (applyProvider && providerRule.getIsLimit() != null && providerRule.getIsLimit() == 0) {
        if (applyProvider && providerRule.getIsLimit() != null && providerRule.getIsLimit() == 1) {
            checkDailyLimitByRule(providerId, providerId, providerRule, providerPointsChange);
        }
@@ -213,7 +221,7 @@
        if (applyProvider && providerPointsChange != 0) {
            PointsFlow providerFlow = new PointsFlow();
            providerFlow.setUserId(providerId);
            providerFlow.setUnitId(providerId);
            providerFlow.setUnitId(null);
            providerFlow.setDataType(ruleType);
            providerFlow.setDataCategory(addPointsFlowDTO.getCategory());
            providerFlow.setPoints(providerPointsChange);
@@ -225,8 +233,8 @@
            if (!providerSaved) {
                throw new BusinessException("保存提供者积分流水失败");
            }
            updateProviderUnitPoints(providerId, providerPointsChange);
            updateUserPointsByRule(providerId, null, userPointsChange);
            // updateProviderUnitPoints(providerId, providerPointsChange);
        }
        return true;
@@ -349,11 +357,14 @@
        QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", 0)
               .eq("user_id", userId)
               .eq("unit_id", unitId)
//               .eq("data_category", pointsRule.getRuleName())
                .eq("rule_id",pointsRule.getId())
                .eq("data_type", 0)
               .ge("flow_time", startOfDay)
               .le("flow_time", endOfDay);
        if(StringUtils.hasText(unitId)){
            wrapper.eq("unit_id", unitId);
        }
        List<PointsFlow> todayFlows = list(wrapper);
        
@@ -381,7 +392,7 @@
     * 检查积分余额是否足够
     */
    private void checkBalanceSufficient(String userId, String unitId, Integer requiredPoints) {
        // 检查个人积分余额
        // 仅检查个人积分余额(移除单位余额判定)
        QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>();
        userWrapper.eq("deleted", 0)
                  .eq("user_id", userId);
@@ -391,15 +402,7 @@
            throw new BusinessException("个人积分余额不足,当前余额: " + (userPoints != null ? userPoints.getBalance() : 0) + ",需要扣除: " + requiredPoints);
        }
        // 检查单位积分余额
        QueryWrapper<UserPoints> unitWrapper = new QueryWrapper<>();
        unitWrapper.eq("deleted", 0)
                  .eq("unit_id", unitId);
        UserPoints unitPoints = userPointsMapper.selectOne(unitWrapper);
        if (unitPoints == null || unitPoints.getBalance() < requiredPoints) {
            throw new BusinessException("单位积分余额不足,当前余额: " + (unitPoints != null ? unitPoints.getBalance() : 0) + ",需要扣除: " + requiredPoints);
        }
        // 原单位余额校验已移除
    }
    /**
@@ -492,7 +495,9 @@
            
            userPoints = new UserPoints();
            userPoints.setUserId(userId);
            userPoints.setUnitId(unitId);
            if(StringUtils.hasText(unitId)){
                userPoints.setUnitId(unitId);
            }
            userPoints.setBalance(pointsValue);
            userPoints.setTotalEarned(pointsValue > 0 ? pointsValue : 0);
            userPoints.setTotalConsumed(pointsValue < 0 ? Math.abs(pointsValue) : 0);
@@ -522,7 +527,7 @@
        }
        // 更新单位积分账户
        QueryWrapper<UserPoints> unitWrapper = new QueryWrapper<>();
         /* QueryWrapper<UserPoints> unitWrapper = new QueryWrapper<>();
        unitWrapper.eq("deleted", 0)
                  .eq("unit_id", unitId);
        
@@ -562,6 +567,92 @@
            
            unitPoints.setUpdateTime(LocalDateTime.now());
            userPointsMapper.updateById(unitPoints);
        } */
    }
    /**
     * 扣减用户积分
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deductUserPoints(DeductUserPointsDTO deductDTO) {
        try {
            String userId = deductDTO.getUserId();
            String providerId = deductDTO.getProviderId();
            String unitId = deductDTO.getUnitId();
            Integer points = deductDTO.getPoints();
            String orderId = deductDTO.getOrderId();
            String remark = deductDTO.getRemark();
            String dataCategory = deductDTO.getDataCategory();
            Integer dataType = deductDTO.getDataType();
            if (!StringUtils.hasText(userId)) {
                throw new BusinessException("用户ID不能为空");
            }
            if (points == null || points <= 0) {
                throw new BusinessException("扣减积分数量必须大于0");
            }
            // 检查用户积分余额是否充足
            checkBalanceSufficient(userId, unitId, points);
            // 创建积分流水记录
            PointsFlow pointsFlow = new PointsFlow();
            pointsFlow.setUserId(userId);
            pointsFlow.setUnitId(unitId);
            pointsFlow.setDataCategory(dataCategory != null ? dataCategory : "积分交易");
            pointsFlow.setDataType(dataType != null ? dataType : 1);
            pointsFlow.setPoints(-points); // 负数表示扣减
            pointsFlow.setName(remark != null ? remark : "积分扣减"); // name字段存储remark内容
            pointsFlow.setFlowTime(LocalDateTime.now());
            pointsFlow.setRlueId(null); // 直接扣减,不关联规则
            boolean saved = save(pointsFlow);
            if (!saved) {
                throw new BusinessException("保存积分流水失败");
            }
            // 更新用户积分账户
            updateUserPointsOnly(userId, -points);
            // 新增积分交易记录(与流水同事务)
            PointsTransaction trans = new PointsTransaction();
            // tb_points_transaction 的 chk_data_category 仅允许 '用户参与'、'其他'
            // 这里将业务类目映射为数据库允许的值
            trans.setDataCategory("用户参与");
            trans.setTransactionName(pointsFlow.getName());
            trans.setTransactionTime(LocalDateTime.now());
            trans.setPointsChange(-points);
            trans.setRuleType("消耗");
            try {
                trans.setUserId(Long.valueOf(userId));
            } catch (Exception ignore) {}
            try {
                if (StringUtils.hasText(unitId)) trans.setUnitId(Long.valueOf(unitId));
            } catch (Exception ignore) {}
            trans.setUserType("个人用户");
            trans.setRuleId(null);
            trans.setDetailId(null);
            trans.setCreatedAt(LocalDateTime.now());
            trans.setDeleted(0);
            int inserted = pointsTransactionMapper.insert(trans);
            log.info("Points transaction inserted rows={}, id={}", inserted, trans.getId());
            if (inserted <= 0 || trans.getId() == null) {
                throw new BusinessException("保存积分交易记录失败");
            }
            // 为提供者新增积分
            AddPointsFlowDTO addPointsFlowDTO = new AddPointsFlowDTO();
            addPointsFlowDTO.setCategory("资源交易");
            addPointsFlowDTO.setCount(1);
            addPointsFlowDTO.setProviderId(providerId);
            addPointsFlowDTO.setRuleType(0);
            addPointsFlowDTO.setRuleNameCode("digital_product_transaction");
            addPointsFlowDTO.setDescription("产品交易");
            addPointsFlowByRule(addPointsFlowDTO);
            return true;
        } catch (Exception e) {
            log.error("扣减用户积分失败", e);
            throw new BusinessException("扣减用户积分失败:" + e.getMessage());
        }
    }
@@ -606,4 +697,40 @@
            userPointsMapper.updateById(unitPoints);
        }
    }
    /**
     * 仅更新个人积分账户(不操作单位账户)
     */
    private void updateUserPointsOnly(String userId, Integer pointsValue) {
        // 更新个人积分账户
        QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>();
        userWrapper.eq("deleted", 0)
                  .eq("user_id", userId);
        UserPoints userPoints = userPointsMapper.selectOne(userWrapper);
        if (userPoints == null) {
            if (pointsValue < 0) {
                throw new BusinessException("个人积分余额不足,无法扣除积分");
            }
            userPoints = new UserPoints();
            userPoints.setUserId(userId);
            userPoints.setUnitId(null);
            userPoints.setBalance(pointsValue);
            userPoints.setTotalEarned(pointsValue > 0 ? pointsValue : 0);
            userPoints.setTotalConsumed(pointsValue < 0 ? Math.abs(pointsValue) : 0);
            userPointsMapper.insert(userPoints);
        } else {
            if (pointsValue < 0 && userPoints.getBalance() + pointsValue < 0) {
                throw new BusinessException("个人积分余额不足,当前余额: " + userPoints.getBalance() + ",需要扣除: " + Math.abs(pointsValue));
            }
            userPoints.setBalance(userPoints.getBalance() + pointsValue);
            if (pointsValue > 0) {
                userPoints.setTotalEarned(userPoints.getTotalEarned() != null ? userPoints.getTotalEarned() + pointsValue : pointsValue);
            }
            if (pointsValue < 0) {
                userPoints.setTotalConsumed(userPoints.getTotalConsumed() != null ? userPoints.getTotalConsumed() + Math.abs(pointsValue) : Math.abs(pointsValue));
            }
            userPoints.setUpdateTime(LocalDateTime.now());
            userPointsMapper.updateById(userPoints);
        }
    }
}