From 7307fad287994fce2567bf4a7bdd4b7d3f06ea83 Mon Sep 17 00:00:00 2001 From: p-honggang.li <p-honggang.li@pcitc.com> Date: 星期三, 03 九月 2025 18:30:53 +0800 Subject: [PATCH] 修改积分交易 --- src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java | 504 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 417 insertions(+), 87 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..14fd125 100644 --- a/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java +++ b/src/main/java/com/webmanage/service/impl/PointsFlowServiceImpl.java @@ -7,12 +7,17 @@ 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; import com.webmanage.entity.PointsRule; 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; @@ -24,6 +29,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; /** * 绉垎娴佹按Service瀹炵幇绫� @@ -38,17 +44,20 @@ @Resource private PointsRuleService pointsRuleService; + @Resource + private PointsTransactionMapper pointsTransactionMapper; + + @Override public PageResult<PointsFlow> getPersonalPointsFlowPage(PointsFlowQueryDTO queryDTO) { - if (queryDTO.getUserId() == null) { + if (!StringUtils.hasText(queryDTO.getUserId())) { throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓虹┖"); } 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 +81,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,97 +126,124 @@ @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("鍙傛暟涓嶈兘涓虹┖"); } - Long userId = addPointsFlowDTO.getUserId(); - Long unitId = addPointsFlowDTO.getUnitId(); - String ruleType = addPointsFlowDTO.getRuleType(); - String ruleName = addPointsFlowDTO.getRuleName(); + String userId = addPointsFlowDTO.getUserId(); + String providerId = addPointsFlowDTO.getProviderId(); + String unitId = addPointsFlowDTO.getUnitId(); + 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); - if (pointsRule == null) { - throw new BusinessException("绉垎瑙勫垯涓嶅瓨鍦ㄦ垨鏈惎鐢�: " + ruleName); + boolean applyUser = StringUtils.hasText(userId) ; + boolean applyProvider = StringUtils.hasText(providerId) ;; + if (!applyUser && !applyProvider) { + throw new BusinessException("userId 涓� providerId 涓嶈兘鍚屾椂涓虹┖"); } - // 楠岃瘉瑙勫垯绫诲瀷鏄惁鍖归厤 - if (!ruleType.equals(pointsRule.getRuleType())) { - throw new BusinessException("瑙勫垯绫诲瀷涓嶅尮閰嶏紝鏈熸湜: " + pointsRule.getRuleType() + "锛屽疄闄�: " + ruleType); + // 鍒嗗埆鑾峰彇鐢ㄦ埛渚�/鎻愪緵鑰呬晶鏈�鏂扮敓鏁堣鍒欙紙鎸� points_winner 杩囨护锛�1鐢ㄦ埛銆�0鎻愪緵鑰咃級 + PointsRule userRule = null; + PointsRule providerRule = null; + if (applyUser) { + userRule = getLatestEffectiveRule(ruleType, ruleNameCode, category, 1); + if (userRule == null) { + throw new BusinessException("鏈壘鍒扮敤鎴蜂晶鐢熸晥瑙勫垯: ruleType=" + ruleType + ", ruleNameCode=" + ruleNameCode + ", category=" + category + ", points_winner=1"); + } + if (!ruleType.equals(userRule.getRuleType())) { + throw new BusinessException("鐢ㄦ埛渚ц鍒欑被鍨嬩笉鍖归厤锛屾湡鏈�: " + userRule.getRuleType() + "锛屽疄闄�: " + ruleType); + } + } + if (applyProvider) { + providerRule = getLatestEffectiveRule(ruleType, ruleNameCode, category, 0); + if (providerRule == null) { + throw new BusinessException("鏈壘鍒版彁渚涜�呬晶鐢熸晥瑙勫垯: ruleType=" + ruleType + ", ruleNameCode=" + ruleNameCode + ", category=" + category + ", points_winner=0"); + } + if (!ruleType.equals(providerRule.getRuleType())) { + throw new BusinessException("鎻愪緵鑰呬晶瑙勫垯绫诲瀷涓嶅尮閰嶏紝鏈熸湜: " + providerRule.getRuleType() + "锛屽疄闄�: " + ruleType); + } } - // 璁$畻绉垎鍊� - Integer basePoints = 0; //pointsRule.getPointsValue() != null ? pointsRule.getPointsValue() : 0; - Integer totalPoints = basePoints * count; - - // 濡傛灉鏄秷璐圭被鍨嬶紝绉垎涓鸿礋鏁� - if ("娑堣垂".equals(ruleType)) { - totalPoints = -totalPoints; + // 璁$畻涓や晶绉垎鍙樺寲锛堝悇鑷寜瑙勫垯璁$畻锛� + int userPointsChange = 0; + int providerPointsChange = 0; + if (applyUser) { + int base = userRule.getPointsValue() != null ? userRule.getPointsValue() : 0; + int amount = base * count; + userPointsChange = (ruleType == RuleTypeEnum.CONSUME.getCode()) ? -Math.abs(amount) : Math.abs(amount); + } + if (applyProvider) { + int base = providerRule.getPointsValue() != null ? providerRule.getPointsValue() : 0; + int amount = base * count; + providerPointsChange = (ruleType == RuleTypeEnum.CONSUME.getCode()) ? -Math.abs(amount) : Math.abs(amount); } - // 妫�鏌ユ瘡鏃ョН鍒嗕笂闄� - if (basePoints > 0) { - checkDailyLimit(userId, unitId, ruleName, totalPoints, 0); + // 姣忔棩涓婇檺鏍¢獙锛堝垎鍒牎楠岋級 + if (applyUser && userRule.getIsLimit() != null && userRule.getIsLimit() == 0) { + checkDailyLimitByRule(userId, unitId, userRule, userPointsChange); + } + if (applyProvider && providerRule.getIsLimit() != null && providerRule.getIsLimit() == 0) { + checkDailyLimitByRule(providerId, providerId, providerRule, providerPointsChange); } - // 鍒涘缓绉垎娴佹按璁板綍 - PointsFlow pointsFlow = new PointsFlow(); - pointsFlow.setUserId(userId); - pointsFlow.setUnitId(unitId); - pointsFlow.setDataType(ruleType); - pointsFlow.setDataCategory(ruleName); - pointsFlow.setPoints(totalPoints); - pointsFlow.setName(addPointsFlowDTO.getDescription() != null ? addPointsFlowDTO.getDescription() : pointsRule.getRuleDescription()); - pointsFlow.setFlowTime(LocalDateTime.now()); - - boolean saved = save(pointsFlow); - if (!saved) { - throw new BusinessException("淇濆瓨绉垎娴佹按澶辫触"); + // 浣欓鏍¢獙锛堜粎鍦ㄦ墸鍑忔椂锛� + if (applyUser && userPointsChange < 0) { + checkBalanceSufficient(userId, unitId, Math.abs(userPointsChange)); + } + if (applyProvider && providerPointsChange < 0) { + checkBalanceSufficient(providerId, providerId, Math.abs(providerPointsChange)); } - // 鏇存柊鐢ㄦ埛绉垎璐︽埛 - updateUserPointsByRule(userId, unitId, totalPoints, ruleType); + // 鐢熸垚鐢ㄦ埛渚ф祦姘村苟鏇存柊璐︽埛 + if (applyUser && userPointsChange != 0) { + PointsFlow pointsFlow = new PointsFlow(); + pointsFlow.setUserId(userId); + pointsFlow.setUnitId(unitId); + pointsFlow.setDataType(ruleType); + pointsFlow.setDataCategory(addPointsFlowDTO.getCategory()); + pointsFlow.setPoints(userPointsChange); + pointsFlow.setName(addPointsFlowDTO.getDescription() != null ? addPointsFlowDTO.getDescription() : userRule.getRuleDescription()); + pointsFlow.setFlowTime(LocalDateTime.now()); + pointsFlow.setRlueId(userRule.getId()); + + boolean saved = save(pointsFlow); + if (!saved) { + throw new BusinessException("淇濆瓨绉垎娴佹按澶辫触"); + } + + updateUserPointsByRule(userId, unitId, userPointsChange); + } + + // 鐢熸垚鎻愪緵鑰呬晶娴佹按骞舵洿鏂拌处鎴� + if (applyProvider && providerPointsChange != 0) { + PointsFlow providerFlow = new PointsFlow(); + providerFlow.setUserId(providerId); + providerFlow.setUnitId(providerId); + providerFlow.setDataType(ruleType); + providerFlow.setDataCategory(addPointsFlowDTO.getCategory()); + providerFlow.setPoints(providerPointsChange); + providerFlow.setName(addPointsFlowDTO.getDescription() != null ? addPointsFlowDTO.getDescription() : providerRule.getRuleDescription()); + providerFlow.setFlowTime(LocalDateTime.now()); + providerFlow.setRlueId(providerRule.getId()); + + boolean providerSaved = save(providerFlow); + if (!providerSaved) { + throw new BusinessException("淇濆瓨鎻愪緵鑰呯Н鍒嗘祦姘村け璐�"); + } + + updateProviderUnitPoints(providerId, providerPointsChange); + } return true; } @Override - public Integer getUserPointsTotal(Long userId) { - if (userId == null) { - return 0; + public UserPoints getUserPointsTotal(String userId) { + if (!StringUtils.hasText(userId)) { + throw new BusinessException("鐢ㄦ埛ID涓嶈兘涓簄ull"); } QueryWrapper<UserPoints> wrapper = new QueryWrapper<>(); @@ -216,13 +251,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 +265,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 +303,107 @@ 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); + } + + /** + * 鏍规嵁ruleType銆乺uleNameCode銆乧ategory銆乸oints_winner鏌ヨ鐢熸晥鏃堕棿鏈�鏂扮殑绉垎瑙勫垯 + */ + private PointsRule getLatestEffectiveRule(Integer ruleType, String ruleNameCode, String category, Integer pointsWinner) { + QueryWrapper<PointsRule> wrapper = new QueryWrapper<>(); + wrapper.eq("is_enabled", 0) + .eq("rule_type", ruleType) + .eq("rule_name_code", ruleNameCode) + .eq("category", category) + .eq(pointsWinner != null, "points_winner", pointsWinner) + .orderByDesc("created_at") + .last("LIMIT 1"); + return pointsRuleService.getOne(wrapper); + } + + /** + * 妫�鏌ユ瘡鏃ョН鍒嗕笂闄愶紙鍩轰簬瑙勫垯锛� + */ + private void checkDailyLimitByRule(String userId, String 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(String userId, String 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); + } + + // 鍘熷崟浣嶄綑棰濇牎楠屽凡绉婚櫎 + } + + /** + * 妫�鏌ユ瘡鏃ョН鍒嗕笂闄愶紙鏃ф柟娉曪紝淇濈暀鍏煎鎬э級 */ private void checkDailyLimit(Long userId, Long unitId, String ruleName, Integer currentPoints, Integer priority) { // 鑾峰彇浠婃棩寮�濮嬪拰缁撴潫鏃堕棿 @@ -290,7 +436,7 @@ /** * 鏇存柊鐢ㄦ埛绉垎 */ - private void updateUserPoints(Long userId, Long unitId, Integer pointsValue) { + private void updateUserPoints(String userId, String unitId, Integer pointsValue) { // 鏇存柊涓汉绉垎 QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>(); userWrapper.eq("deleted", 0) @@ -331,7 +477,7 @@ /** * 鏍规嵁瑙勫垯鏇存柊鐢ㄦ埛绉垎璐︽埛 */ - private void updateUserPointsByRule(Long userId, Long unitId, Integer pointsValue, String ruleType) { + private void updateUserPointsByRule(String userId, String unitId, Integer pointsValue) { // 鏇存柊涓汉绉垎璐︽埛 QueryWrapper<UserPoints> userWrapper = new QueryWrapper<>(); userWrapper.eq("deleted", 0) @@ -339,6 +485,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 +498,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 +528,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 +541,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); // 鏇存柊绱鑾峰彇绉垎 @@ -398,4 +564,168 @@ userPointsMapper.updateById(unitPoints); } } + + /** + * 鎵e噺鐢ㄦ埛绉垎 + */ + @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("鎵e噺绉垎鏁伴噺蹇呴』澶т簬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); // 璐熸暟琛ㄧず鎵e噺 + pointsFlow.setName(remark != null ? remark : "绉垎鎵e噺"); // name瀛楁瀛樺偍remark鍐呭 + pointsFlow.setFlowTime(LocalDateTime.now()); + pointsFlow.setRlueId(null); // 鐩存帴鎵e噺锛屼笉鍏宠仈瑙勫垯 + + 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噺鐢ㄦ埛绉垎澶辫触", e); + throw new BusinessException("鎵e噺鐢ㄦ埛绉垎澶辫触锛�" + e.getMessage()); + } + } + + /** + * 浠呮洿鏂版彁渚涜�咃紙鍗曚綅锛夌Н鍒嗚处鎴� + */ + private void updateProviderUnitPoints(String providerUnitId, Integer pointsValue) { + QueryWrapper<UserPoints> unitWrapper = new QueryWrapper<>(); + unitWrapper.eq("deleted", 0) + .eq("unit_id", providerUnitId); + + UserPoints unitPoints = userPointsMapper.selectOne(unitWrapper); + if (unitPoints == null) { + if (pointsValue < 0) { + throw new BusinessException("鎻愪緵鑰呯Н鍒嗕綑棰濅笉瓒筹紝鏃犳硶鎵i櫎绉垎"); + } + + unitPoints = new UserPoints(); + unitPoints.setUserId(null); + unitPoints.setUnitId(providerUnitId); + unitPoints.setBalance(pointsValue); + unitPoints.setTotalEarned(pointsValue > 0 ? pointsValue : 0); + 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); + + if (pointsValue > 0) { + unitPoints.setTotalEarned(unitPoints.getTotalEarned() != null ? + unitPoints.getTotalEarned() + pointsValue : pointsValue); + } + if (pointsValue < 0) { + unitPoints.setTotalConsumed(unitPoints.getTotalConsumed() != null ? + unitPoints.getTotalConsumed() + Math.abs(pointsValue) : Math.abs(pointsValue)); + } + + unitPoints.setUpdateTime(LocalDateTime.now()); + 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); + } + } } -- Gitblit v1.8.0