From 1b1248f500a49f11f12c3cf9b469c300430b4514 Mon Sep 17 00:00:00 2001
From: p-honggang.li <p-honggang.li@pcitc.com>
Date: 星期一, 18 八月 2025 10:02:03 +0800
Subject: [PATCH] Merge branch 'master' of http://xearth.cn:6600/r/web-manage/web-manage-back

---
 src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java |  219 ++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 160 insertions(+), 59 deletions(-)

diff --git a/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java b/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java
index 9188feb..8cdf5be 100644
--- a/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java
+++ b/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java
@@ -8,6 +8,7 @@
 import com.webmanage.common.PageResult;
 import com.webmanage.dto.AddPointsFlowDTO;
 import com.webmanage.dto.PointsFlowQueryDTO;
+import com.webmanage.emun.RuleTypeEnum;
 import com.webmanage.entity.PointsFlow;
 import com.webmanage.entity.PointsRule;
 import com.webmanage.entity.UserPoints;
@@ -24,6 +25,7 @@
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * 绉垎娴佹按Service瀹炵幇绫�
@@ -47,8 +49,7 @@
         Page<PointsFlow> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
         
         QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>();
-        wrapper.eq("deleted", 0)
-               .eq("user_id", queryDTO.getUserId());
+        wrapper.eq("user_id", queryDTO.getUserId());
         
         buildQueryWrapper(wrapper, queryDTO);
         
@@ -72,8 +73,7 @@
         Page<PointsFlow> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
         
         QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>();
-        wrapper.eq("deleted", 0)
-               .eq("unit_id", queryDTO.getUnitId());
+        wrapper.eq("unit_id", queryDTO.getUnitId());
         
         buildQueryWrapper(wrapper, queryDTO);
         
@@ -118,36 +118,6 @@
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean recordPointsFlow(Long userId, Long unitId, String flowType, String pointsSource, 
-                                  Integer pointsValue, String orderId, String description) {
-        if (userId == null || unitId == null || !StringUtils.hasText(flowType) || 
-            !StringUtils.hasText(pointsSource) || pointsValue == null) {
-            throw new BusinessException("鍙傛暟涓嶅畬鏁�");
-        }
-
-        // 鍒涘缓绉垎娴佹按璁板綍
-        PointsFlow pointsFlow = new PointsFlow();
-        pointsFlow.setUserId(userId);
-        pointsFlow.setUnitId(unitId);
-        pointsFlow.setDataType(flowType);
-        pointsFlow.setDataCategory(pointsSource);
-        pointsFlow.setPoints(pointsValue);
-        pointsFlow.setName(description);
-        pointsFlow.setFlowTime(LocalDateTime.now());
-
-        boolean saved = save(pointsFlow);
-        if (!saved) {
-            throw new BusinessException("淇濆瓨绉垎娴佹按澶辫触");
-        }
-
-        // 鏇存柊鐢ㄦ埛绉垎
-        updateUserPoints(userId, unitId, pointsValue);
-
-        return true;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
     public boolean addPointsFlowByRule(AddPointsFlowDTO addPointsFlowDTO) {
         if (addPointsFlowDTO == null) {
             throw new BusinessException("鍙傛暟涓嶈兘涓虹┖");
@@ -155,14 +125,15 @@
 
         Long userId = addPointsFlowDTO.getUserId();
         Long unitId = addPointsFlowDTO.getUnitId();
-        String ruleType = addPointsFlowDTO.getRuleType();
-        String ruleName = addPointsFlowDTO.getRuleName();
+        Integer ruleType = addPointsFlowDTO.getRuleType();
+        String category = addPointsFlowDTO.getCategory();
+        String ruleNameCode = addPointsFlowDTO.getRuleNameCode();
         Integer count = addPointsFlowDTO.getCount() != null ? addPointsFlowDTO.getCount() : 1;
 
-        // 鏌ヨ绉垎瑙勫垯
-        PointsRule pointsRule = pointsRuleService.getRuleByTriggerCondition(ruleName);
+        // 鏍规嵁ruleType銆乺uleNameCode銆乧ategory鏌ヨ鐢熸晥鏃堕棿鏈�鏂扮殑绉垎瑙勫垯
+        PointsRule pointsRule = getLatestEffectiveRule(ruleType, ruleNameCode, category);
         if (pointsRule == null) {
-            throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦ㄦ垨鏈惎鐢�: " + ruleName);
+            throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦ㄦ垨鏈惎鐢�: ruleType=" + ruleType + ", ruleNameCode=" + ruleNameCode + ", category=" + category);
         }
 
         // 楠岃瘉瑙勫垯绫诲瀷鏄惁鍖归厤
@@ -171,17 +142,22 @@
         }
 
         // 璁$畻绉垎鍊�
-        Integer basePoints = 0; //pointsRule.getPointsValue() != null ? pointsRule.getPointsValue() : 0;
+        Integer basePoints = pointsRule.getPointsValue() != null ? pointsRule.getPointsValue() : 0;
         Integer totalPoints = basePoints * count;
 
         // 濡傛灉鏄秷璐圭被鍨嬶紝绉垎涓鸿礋鏁�
-        if ("娑堣垂".equals(ruleType)) {
+        if (ruleType == RuleTypeEnum.CONSUME.getCode()) { // 1琛ㄧず娑堣垂绫诲瀷
             totalPoints = -totalPoints;
         }
 
         // 妫�鏌ユ瘡鏃ョН鍒嗕笂闄�
-        if (basePoints > 0) {
-            checkDailyLimit(userId, unitId, ruleName, totalPoints, 0);
+        if (pointsRule.getIsLimit() != null && pointsRule.getIsLimit() == 0) { // 0琛ㄧず鏈夋瘡鏃ヤ笂闄�
+            checkDailyLimitByRule(userId, unitId, pointsRule, totalPoints);
+        }
+
+        // 濡傛灉鏄墸绉垎鎿嶄綔锛屽厛妫�鏌ヤ綑棰濇槸鍚﹁冻澶�
+        if (totalPoints < 0) {
+            checkBalanceSufficient(userId, unitId, Math.abs(totalPoints));
         }
 
         // 鍒涘缓绉垎娴佹按璁板綍
@@ -189,10 +165,11 @@
         pointsFlow.setUserId(userId);
         pointsFlow.setUnitId(unitId);
         pointsFlow.setDataType(ruleType);
-        pointsFlow.setDataCategory(ruleName);
+        pointsFlow.setDataCategory(addPointsFlowDTO.getCategory());
         pointsFlow.setPoints(totalPoints);
         pointsFlow.setName(addPointsFlowDTO.getDescription() != null ? addPointsFlowDTO.getDescription() : pointsRule.getRuleDescription());
         pointsFlow.setFlowTime(LocalDateTime.now());
+        pointsFlow.setRlueId(pointsRule.getId());
 
         boolean saved = save(pointsFlow);
         if (!saved) {
@@ -200,15 +177,15 @@
         }
 
         // 鏇存柊鐢ㄦ埛绉垎璐︽埛
-        updateUserPointsByRule(userId, unitId, totalPoints, ruleType);
+        updateUserPointsByRule(userId, unitId, totalPoints);
 
         return true;
     }
 
     @Override
-    public Integer getUserPointsTotal(Long userId) {
+    public UserPoints getUserPointsTotal(Long userId) {
         if (userId == null) {
-            return 0;
+            throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓簄ull");
         }
         
         QueryWrapper<UserPoints> wrapper = new QueryWrapper<>();
@@ -216,13 +193,13 @@
                .eq("user_id", userId);
         
         UserPoints userPoints = userPointsMapper.selectOne(wrapper);
-        return userPoints != null ? userPoints.getBalance() : 0;
+        return userPoints ;
     }
 
     @Override
-    public Integer getUnitPointsTotal(Long unitId) {
+    public UserPoints getUnitPointsTotal(Long unitId) {
         if (unitId == null) {
-            return 0;
+            throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓簄ull");
         }
         
         QueryWrapper<UserPoints> wrapper = new QueryWrapper<>();
@@ -230,15 +207,37 @@
                .eq("unit_id", unitId);
         
         UserPoints userPoints = userPointsMapper.selectOne(wrapper);
-        return userPoints != null ? userPoints.getBalance() : 0;
+        return userPoints;
+    }
+
+    @Override
+    public List<String> getPointsFlowCategories() {
+        QueryWrapper<PointsFlow> wrapper = new QueryWrapper<>();
+        wrapper.select("DISTINCT data_category")
+               .isNotNull("data_category")
+               .ne("data_category", "")
+               .ne("data_category", "null")
+               .eq("deleted", 0)
+               .orderByAsc("data_category");
+        
+        List<PointsFlow> flows = list(wrapper);
+        return flows.stream()
+                .map(PointsFlow::getDataCategory)
+                .filter(category -> category != null && !category.trim().isEmpty())
+                .distinct()
+                .sorted()
+                .collect(Collectors.toList());
     }
 
     /**
      * 鏋勫缓鏌ヨ鏉′欢
      */
     private void buildQueryWrapper(QueryWrapper<PointsFlow> wrapper, PointsFlowQueryDTO queryDTO) {
-        if (StringUtils.hasText(queryDTO.getFlowType())) {
-            wrapper.eq("flow_type", queryDTO.getFlowType());
+        if(StringUtils.hasText(queryDTO.getDataCategory())){
+            wrapper.eq("data_category", queryDTO.getDataCategory());
+        }
+        if (queryDTO.getDataType()!=null) {
+            wrapper.eq("data_type", queryDTO.getDataType());
         }
         if (StringUtils.hasText(queryDTO.getPointsSource())) {
             wrapper.eq("points_source", queryDTO.getPointsSource());
@@ -246,18 +245,100 @@
         if (StringUtils.hasText(queryDTO.getOrderId())) {
             wrapper.eq("order_id", queryDTO.getOrderId());
         }
-        if (queryDTO.getStartTime() != null) {
-            wrapper.ge("flow_time", queryDTO.getStartTime());
+        if (queryDTO.getFlowEndTime() != null) {
+            wrapper.ge("flow_time", queryDTO.getFlowStartTime());
         }
-        if (queryDTO.getEndTime() != null) {
-            wrapper.le("flow_time", queryDTO.getEndTime());
+        if (queryDTO.getFlowEndTime() != null) {
+            wrapper.le("flow_time", queryDTO.getFlowEndTime());
         }
         
         wrapper.orderByDesc("flow_time");
     }
 
     /**
-     * 妫�鏌ユ瘡鏃ョН鍒嗕笂闄�
+     * 鏍规嵁ruleType銆乺uleNameCode銆乧ategory鏌ヨ鐢熸晥鏃堕棿鏈�鏂扮殑绉垎瑙勫垯
+     */
+    private PointsRule getLatestEffectiveRule(Integer ruleType, String ruleNameCode, String category) {
+        QueryWrapper<PointsRule> wrapper = new QueryWrapper<>();
+        wrapper.eq("deleted", 0)
+               .eq("is_enabled", 0) // 0琛ㄧず鍚敤
+               .eq("rule_type", ruleType)
+               .eq("rule_name_code", ruleNameCode)
+               .eq("category", category)
+               .orderByDesc("created_at") // 鎸夊垱寤烘椂闂村�掑簭锛岃幏鍙栨渶鏂扮殑瑙勫垯
+               .last("LIMIT 1");
+        
+        return pointsRuleService.getOne(wrapper);
+    }
+
+    /**
+     * 妫�鏌ユ瘡鏃ョН鍒嗕笂闄愶紙鍩轰簬瑙勫垯锛�
+     */
+    private void checkDailyLimitByRule(Long userId, Long unitId, PointsRule pointsRule, Integer currentPoints) {
+        // 鑾峰彇浠婃棩寮�濮嬪拰缁撴潫鏃堕棿
+        LocalDate today = LocalDate.now();
+        LocalDateTime startOfDay = today.atStartOfDay();
+        LocalDateTime endOfDay = today.atTime(23, 59, 59);
+
+        // 鏌ヨ浠婃棩璇ヨ鍒欑殑绉垎娴佹按
+        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())
+               .ge("flow_time", startOfDay)
+               .le("flow_time", endOfDay);
+
+        List<PointsFlow> todayFlows = list(wrapper);
+        
+        // 璁$畻浠婃棩绱绉垎
+        int todayTotal = todayFlows.stream()
+                .mapToInt(flow -> flow.getPoints() != null ? flow.getPoints() : 0)
+                .sum();
+
+        // 鑾峰彇瑙勫垯鐨勬瘡鏃ョН鍒嗕笂闄�
+        Integer dailyLimit = pointsRule.getDailyLimit();
+        if (dailyLimit != null && dailyLimit > 0) {
+            // 濡傛灉浠婃棩绱绉垎瓒呰繃姣忔棩涓婇檺锛屽垯鎶涘嚭寮傚父
+            if (Math.abs(todayTotal) >= dailyLimit) {
+                throw new BusinessException("浠婃棩璇ヨ鍒欑Н鍒嗗凡杈句笂闄�: " + dailyLimit);
+            }
+            
+            // 濡傛灉鍔犱笂褰撳墠绉垎浼氳秴杩囨瘡鏃ヤ笂闄愶紝鍒欐姏鍑哄紓甯�
+            if (Math.abs(todayTotal + currentPoints) > dailyLimit) {
+                throw new BusinessException("鏈绉垎鎿嶄綔灏嗚秴杩囨瘡鏃ヤ笂闄�: " + dailyLimit + "锛屽綋鍓嶅凡绱: " + Math.abs(todayTotal));
+            }
+        }
+    }
+
+    /**
+     * 妫�鏌ョН鍒嗕綑棰濇槸鍚﹁冻澶�
+     */
+    private void checkBalanceSufficient(Long userId, Long unitId, Integer requiredPoints) {
+        // 妫�鏌ヤ釜浜虹Н鍒嗕綑棰�
+        QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>();
+        userWrapper.eq("deleted", 0)
+                  .eq("user_id", userId);
+        
+        UserPoints userPoints = userPointsMapper.selectOne(userWrapper);
+        if (userPoints == null || userPoints.getBalance() < requiredPoints) {
+            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);
+        }
+    }
+
+    /**
+     * 妫�鏌ユ瘡鏃ョН鍒嗕笂闄愶紙鏃ф柟娉曪紝淇濈暀鍏煎鎬э級
      */
     private void checkDailyLimit(Long userId, Long unitId, String ruleName, Integer currentPoints, Integer priority) {
         // 鑾峰彇浠婃棩寮�濮嬪拰缁撴潫鏃堕棿
@@ -331,7 +412,7 @@
     /**
      * 鏍规嵁瑙勫垯鏇存柊鐢ㄦ埛绉垎璐︽埛
      */
-    private void updateUserPointsByRule(Long userId, Long unitId, Integer pointsValue, String ruleType) {
+    private void updateUserPointsByRule(Long userId, Long unitId, Integer pointsValue) {
         // 鏇存柊涓汉绉垎璐︽埛
         QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>();
         userWrapper.eq("deleted", 0)
@@ -339,6 +420,11 @@
         
         UserPoints userPoints = userPointsMapper.selectOne(userWrapper);
         if (userPoints == null) {
+            // 濡傛灉鏄柊鐢ㄦ埛涓旀槸鎵gН鍒嗘搷浣滐紝浣欓涓嶈冻
+            if (pointsValue < 0) {
+                throw new BusinessException("绉垎浣欓涓嶈冻锛屾棤娉曟墸闄ょН鍒�");
+            }
+            
             userPoints = new UserPoints();
             userPoints.setUserId(userId);
             userPoints.setUnitId(unitId);
@@ -347,6 +433,11 @@
             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);
             
             // 鏇存柊绱鑾峰彇绉垎
@@ -372,6 +463,11 @@
         
         UserPoints unitPoints = userPointsMapper.selectOne(unitWrapper);
         if (unitPoints == null) {
+            // 濡傛灉鏄柊鍗曚綅涓旀槸鎵gН鍒嗘搷浣滐紝浣欓涓嶈冻
+            if (pointsValue < 0) {
+                throw new BusinessException("鍗曚綅绉垎浣欓涓嶈冻锛屾棤娉曟墸闄ょН鍒�");
+            }
+            
             unitPoints = new UserPoints();
             unitPoints.setUserId(userId);
             unitPoints.setUnitId(unitId);
@@ -380,6 +476,11 @@
             unitPoints.setTotalConsumed(pointsValue < 0 ? Math.abs(pointsValue) : 0);
             userPointsMapper.insert(unitPoints);
         } else {
+            // 妫�鏌ユ墸绉垎鏃朵綑棰濇槸鍚﹁冻澶�
+            if (pointsValue < 0 && unitPoints.getBalance() + pointsValue < 0) {
+                throw new BusinessException("鍗曚綅绉垎浣欓涓嶈冻锛屽綋鍓嶄綑棰�: " + unitPoints.getBalance() + "锛岄渶瑕佹墸闄�: " + Math.abs(pointsValue));
+            }
+            
             unitPoints.setBalance(unitPoints.getBalance() + pointsValue);
             
             // 鏇存柊绱鑾峰彇绉垎

--
Gitblit v1.8.0