ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java
@@ -6,6 +6,7 @@ import com.ruoyi.common.core.domain.R; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.web.bind.annotation.PostMapping; import java.util.List; @@ -22,6 +23,7 @@ public AppUserClient create(Throwable cause) { return new AppUserClient() { @PostMapping("/appUser/getAppUserById") @Override public AppUser getAppUserById(Long id) { log.error("根据id获取用户失败:{}", cause.getMessage()); @@ -45,6 +47,12 @@ log.error("获取用户门店信息失败:{}", cause.getMessage()); throw new RuntimeException("获取用户门店信息失败"); } @Override public R<List<AppUser>> getUserAncestorList(Long id) { log.error("获取用户祖籍列表失败:{}", cause.getMessage()); throw new RuntimeException("获取用户祖籍列表失败"); } }; } } ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserClient.java
@@ -43,4 +43,10 @@ @GetMapping("/appUserShop/shop/{userId}") R<List<AppUserShop>> getAppUserShop(@PathVariable("userId") Long userId); /** * 根据用户id获取用户的祖籍列表 */ @GetMapping("/appletLogin/getUserAncestorList") R<List<AppUser>> getUserAncestorList(@RequestParam("id") Long id); } ruoyi-api/ruoyi-api-order/src/main/java/model/Order.java
@@ -44,6 +44,10 @@ @TableField("order_status") private Integer orderStatus; @ApiModelProperty(value = "是否已分佣: 0-否 1-是") @TableField("is_commission") private Integer isCommission; @ApiModelProperty(value = "核销时间") @TableField("end_time") private LocalDateTime endTime; ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/task/AfterSalesTask.java
@@ -14,7 +14,7 @@ private RedisTemplate<String, String> redisTemplate; /** * 计算佣金 * 计算佣金(设置每分钟执行一次) */ public void afterSales() { @@ -22,15 +22,18 @@ // 从延迟队列中获取需要处理的订单 Set<String> orderIds = redisTemplate.opsForZSet().rangeByScore("delay_queue:commission", 0, now); if (orderIds != null && !orderIds.isEmpty()) { for (String orderId : orderIds) { try { Long id = Long.parseLong(orderId); } catch (NumberFormatException e) { log.error("延迟队列中的订单ID无效: {}", orderId, e); } } // 处理完后移除已处理的订单 redisTemplate.opsForZSet().removeRangeByScore("delay_queue:commission", 0, now); } } /** * 佣金补偿(每天执行一次) * redis未配置持久化,为防止数据丢失,每天执行一次,将到期未处理的订单重新放入延迟队列中 */ public void afterSalesCompensation() { // 获取未处理的订单 } } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserController.java
@@ -185,6 +185,15 @@ } /** * 获取用户的祖籍列表 */ @GetMapping("/getUserAncestorList") public R<List<AppUser>> getUserAncestorList(Long id){ List<AppUser> list = appUserService.getUserAncestorList(id,null); return R.ok(list); } } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/AppUserService.java
@@ -57,4 +57,9 @@ * @return */ List<NearbyReferrerVo> getNearbyReferrer(NearbyReferrer nearbyReferrer); /** * 获取用户的祖籍列表 */ List<AppUser> getUserAncestorList(Long id,List<AppUser> list); } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/AppUserServiceImpl.java
@@ -18,14 +18,13 @@ import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.feignClient.SysUserClient; import com.ruoyi.system.api.model.LoginUser; import org.checkerframework.checker.units.qual.A; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.*; /** * <p> @@ -330,4 +329,38 @@ List<NearbyReferrerVo> list = this.baseMapper.getNearbyReferrer(cityCode, nearbyReferrer); return list; } @Override public List<AppUser> getUserAncestorList(Long id, List<AppUser> list) { if (list == null) { list = new ArrayList<>(); } Set<Long> visitedIds = new HashSet<>(); Long currentId = id; while (currentId != null && !visitedIds.contains(currentId)) { AppUser appUser = getById(currentId); if (appUser == null) { break; // 如果用户不存在,终止循环 } Long inviteUserId = appUser.getInviteUserId(); if (inviteUserId != null) { AppUser invitedUser = getById(inviteUserId); if (invitedUser != null) { list.add(invitedUser); visitedIds.add(currentId); currentId = inviteUserId; } else { break; // 如果邀请用户不存在,终止循环 } } else { break; // 如果没有邀请用户,终止循环 } } return list; } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/CommissionService.java
New file @@ -0,0 +1,12 @@ package com.ruoyi.order.service; import java.time.LocalDateTime; import java.util.List; public interface CommissionService { // 计算佣金 void calculationCommission(List<Long> orderIds); void addToCommissionDelayQueue(Long orderId, LocalDateTime afterSalesDeadline); } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/OrderService.java
@@ -23,4 +23,6 @@ boolean check(Order order, Integer shopId, Long userId); void writeOff(String code,Integer shopId); void commission(Long orderId); } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/CommissionServiceImpl.java
New file @@ -0,0 +1,111 @@ package com.ruoyi.order.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.account.api.feignClient.AppUserClient; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.common.core.domain.R; import com.ruoyi.order.service.CommissionService; import com.ruoyi.order.service.OrderGoodService; import com.ruoyi.order.service.OrderService; import com.ruoyi.other.api.domain.Shop; import com.ruoyi.other.api.feignClient.ShopClient; import model.Order; import model.OrderGood; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service public class CommissionServiceImpl implements CommissionService { @Resource private OrderService orderService; @Resource private OrderGoodService orderGoodService; @Resource private AppUserClient appUserClient; @Resource private ShopClient shopClient; @Resource private RedisTemplate<String, String> redisTemplate; /** * 返佣延迟队列(redis有序集合) * * @param orderId 订单ID * @param afterSalesDeadline 售后截止日期(计算日期) */ @Override public void addToCommissionDelayQueue(Long orderId, LocalDateTime afterSalesDeadline) { // 获取订单售后截止日期时间戳(秒) long deadlineTimestamp = afterSalesDeadline.atZone(ZoneId.systemDefault()).toEpochSecond(); redisTemplate.opsForZSet().add("delay_queue:commission", orderId.toString(), deadlineTimestamp); } @Override public void calculationCommission(List<Long> orderIds) { List<OrderGood> orderGoods = orderGoodService.list(new LambdaQueryWrapper<OrderGood>() .in(OrderGood::getOrderId, orderIds)); Map<Long, List<OrderGood>> ogMap = orderGoods.stream().collect(Collectors.groupingBy(OrderGood::getOrderId)); for (Map.Entry<Long, List<OrderGood>> entry : ogMap.entrySet()) { Long k = entry.getKey(); List<OrderGood> v = entry.getValue(); Order order = orderService.getById(k); if (order.getIsCommission() == 1) { continue; } R<Shop> r = shopClient.getShopById(order.getShopId()); if (!R.isSuccess(r)) { throw new RuntimeException("获取门店信息失败"); } Shop shop = r.getData(); if (shop == null) { throw new RuntimeException("获取门店信息失败"); } Long appUserId = order.getAppUserId(); AppUser appUser = appUserClient.getAppUserById(appUserId); if (appUser == null) { throw new RuntimeException("获取用户信息失败"); } Long inviteUserId = appUser.getInviteUserId(); AppUser inviteUser = appUserClient.getAppUserById(inviteUserId); for (OrderGood og : v) {// 累计分销金额 // 上级分销金额 if (inviteUser != null){ BigDecimal superiorSubcommission = og.getSuperiorSubcommission(); BigDecimal totalDistributionAmount = inviteUser.getTotalDistributionAmount(); totalDistributionAmount = totalDistributionAmount.add(superiorSubcommission); // Integer superiorType = og.getSuperiorType(); Integer sharePoint = inviteUser.getSharePoint(); if (superiorType == 1) { Integer superiorRebatePoints = og.getSuperiorRebatePoints(); sharePoint = sharePoint + superiorRebatePoints; } else if (superiorType == 2) { } else { continue; } inviteUser.setTotalDistributionAmount(totalDistributionAmount); inviteUser.setSharePoint(sharePoint); } // 门店分销金额 og.getBoundShopCharges() } } } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java
@@ -57,8 +57,7 @@ private TokenService tokenService; @Resource private TechnicianClient technicianClient; @Resource private RedisTemplate<String, String> redisTemplate; @Override public List<OrderVO> selectOrderListByUserId(Integer status, Long userId) { @@ -191,15 +190,9 @@ } /** * 返佣延迟队列 * * @param orderId 订单ID * @param afterSalesDeadline 售后截止日期(计算日期) */ private void addToCommissionDelayQueue(Long orderId, LocalDateTime afterSalesDeadline) { // 获取订单售后截止日期时间戳(秒) long deadlineTimestamp = afterSalesDeadline.atZone(ZoneId.systemDefault()).toEpochSecond(); redisTemplate.opsForZSet().add("delay_queue:commission", orderId.toString(), deadlineTimestamp); @Override public void commission(Long orderId) { } }