diff --git a/src/main/java/com/gxwebsoft/shop/entity/ShopDealerReferee.java b/src/main/java/com/gxwebsoft/shop/entity/ShopDealerReferee.java index a4f54db..24ac1f5 100644 --- a/src/main/java/com/gxwebsoft/shop/entity/ShopDealerReferee.java +++ b/src/main/java/com/gxwebsoft/shop/entity/ShopDealerReferee.java @@ -67,10 +67,6 @@ public class ShopDealerReferee implements Serializable { @Schema(description = "推荐关系层级(弃用)") private Integer level; - @Schema(description = "上级是否门店分红用户(ShopDealerUser.type=1;扩展字段)") - @TableField(exist = false) - private Boolean isShopRole; - @Schema(description = "来源(如 goods_share)") // NOTE: 表 shop_dealer_referee 若未新增该字段,需要 exist=false,避免 MyBatis-Plus 自动生成SQL时报 Unknown column。 @TableField(exist = false) diff --git a/src/main/java/com/gxwebsoft/shop/mapper/ShopDealerRefereeMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/ShopDealerRefereeMapper.java index 388cd76..70ddf37 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/ShopDealerRefereeMapper.java +++ b/src/main/java/com/gxwebsoft/shop/mapper/ShopDealerRefereeMapper.java @@ -34,22 +34,4 @@ public interface ShopDealerRefereeMapper extends BaseMapper { */ List selectListRel(@Param("param") ShopDealerRefereeParam param); - /** - * 查询指定用户的推荐关系链路(按 level 升序),并计算每个上级是否包含门店角色(shop)。 - *

- * 用于定时任务分佣:按 ShopDealerUser.type=1 判定“门店分红”上级,避免查询 core 的 sys_user_role。 - *

- * 注意:对应XML里为了兼容 MyBatis-Plus 的 SQL 解析,limit 使用字面量拼接(${limit}), - * 这里的 limit 必须由服务端常量传入(不要透传用户输入)。 - */ - List selectRefereeChainWithShopRole(@Param("tenantId") Integer tenantId, - @Param("userId") Integer userId, - @Param("limit") Integer limit); - - /** - * 查询指定用户的一级推荐人(level=1),并按 ShopDealerUser.type=1 判定该推荐人是否为“门店分红”上级。 - */ - ShopDealerReferee selectFirstLevelRefereeWithShopRole(@Param("tenantId") Integer tenantId, - @Param("userId") Integer userId); - } diff --git a/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopDealerRefereeMapper.xml b/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopDealerRefereeMapper.xml index 4d6afb4..a8635f1 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopDealerRefereeMapper.xml +++ b/src/main/java/com/gxwebsoft/shop/mapper/xml/ShopDealerRefereeMapper.xml @@ -8,7 +8,6 @@ d.nickname AS dealerName, d.avatar AS dealerAvatar, d.phone AS dealerPhone, - CASE WHEN du.user_id IS NULL THEN 0 ELSE 1 END AS isShopRole, u.nickname, u.avatar, u.alias, @@ -16,11 +15,6 @@ u.is_admin as isAdmin FROM shop_dealer_referee a INNER JOIN gxwebsoft_core.sys_user d ON a.dealer_id = d.user_id AND d.deleted = 0 - LEFT JOIN shop_dealer_user du - ON du.user_id = a.dealer_id - AND du.tenant_id = a.tenant_id - AND du.type = 1 - AND (du.is_delete = 0 OR du.is_delete IS NULL) INNER JOIN gxwebsoft_core.sys_user u ON a.user_id = u.user_id AND u.deleted = 0 @@ -64,50 +58,4 @@ - - - - - - diff --git a/src/main/java/com/gxwebsoft/shop/task/DealerOrderSettlement10584Task.java b/src/main/java/com/gxwebsoft/shop/task/DealerOrderSettlement10584Task.java index f1a6a4d..19a39e8 100644 --- a/src/main/java/com/gxwebsoft/shop/task/DealerOrderSettlement10584Task.java +++ b/src/main/java/com/gxwebsoft/shop/task/DealerOrderSettlement10584Task.java @@ -10,7 +10,6 @@ import com.gxwebsoft.shop.entity.ShopDealerUser; import com.gxwebsoft.shop.entity.ShopOrder; import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.mapper.UserMapper; -import com.gxwebsoft.shop.mapper.ShopDealerRefereeMapper; import com.gxwebsoft.shop.service.ShopDealerCapitalService; import com.gxwebsoft.shop.service.ShopDealerOrderService; import com.gxwebsoft.shop.service.ShopDealerRefereeService; @@ -46,6 +45,7 @@ public class DealerOrderSettlement10584Task { private static final int MAX_ORDERS_PER_RUN = 50; private static final int MAX_REFEREE_CHAIN_DEPTH = 20; + private static final int DIVIDEND_SCALE = 3; @Resource private TransactionTemplate transactionTemplate; @@ -65,16 +65,13 @@ public class DealerOrderSettlement10584Task { @Resource private ShopDealerOrderService shopDealerOrderService; - @Resource - private ShopDealerRefereeMapper shopDealerRefereeMapper; - @Resource private UserMapper userMapper; /** * 每30秒执行一次。 */ - @Scheduled(cron = "0/30 * * * * ?") + @Scheduled(cron = "0/20 * * * * ?") @IgnoreTenant("该定时任务仅处理租户10584,但需要显式按tenantId过滤,避免定时任务线程无租户上下文导致查询异常") public void settleTenant10584Orders() { try { @@ -199,8 +196,8 @@ public class DealerOrderSettlement10584Task { } private ShopRoleCommission settleShopRoleRefereeCommission(ShopOrder order, BigDecimal baseAmount) { - List shopRoleReferees = findFirstTwoShopRoleRefereesByDealerReferee(order.getUserId()); - log.info("门店(type=1)上级链路结果 - orderNo={}, buyerUserId={}, shopRoleReferees={}", + List shopRoleReferees = findFirstTwoUpstreamReferees(order.getUserId()); + log.info("分红上级链路结果(level=1链路取前两级) - orderNo={}, buyerUserId={}, referees={}", order.getOrderNo(), order.getUserId(), shopRoleReferees); if (shopRoleReferees.isEmpty()) { return ShopRoleCommission.empty(); @@ -208,23 +205,28 @@ public class DealerOrderSettlement10584Task { if (shopRoleReferees.size() == 1) { // 门店直推:2% - BigDecimal money = calcMoney(baseAmount, RATE_0_02); - log.info("门店直推/简推发放(仅1人) - orderNo={}, storeDirectUserId={}, money={}", order.getOrderNo(), shopRoleReferees.get(0), money); - creditDealerCommission(shopRoleReferees.get(0), money, order, order.getUserId(), "门店直推佣金(type=1,仅1人,2%)"); + BigDecimal money = calcDividendMoney(baseAmount, RATE_0_02); + log.info("分红发放(仅1人) - orderNo={}, firstDividendUserId={}, money={}", order.getOrderNo(), shopRoleReferees.get(0), money); + creditDealerCommission(shopRoleReferees.get(0), money, order, order.getUserId(), "门店直推佣金(仅1人,2%)"); return new ShopRoleCommission(shopRoleReferees.get(0), money, null, BigDecimal.ZERO); } // 两个或以上:第一个0.02,第二个0.01 - BigDecimal storeDirectMoney = calcMoney(baseAmount, RATE_0_02); - BigDecimal storeSimpleMoney = calcMoney(baseAmount, RATE_0_01); - log.info("门店直推/门店简推发放 - orderNo={}, storeDirectUserId={}, storeDirectMoney={}, storeSimpleUserId={}, storeSimpleMoney={}", + BigDecimal storeDirectMoney = calcDividendMoney(baseAmount, RATE_0_02); + BigDecimal storeSimpleMoney = calcDividendMoney(baseAmount, RATE_0_01); + log.info("分红发放(2人) - orderNo={}, firstDividendUserId={}, firstDividendMoney={}, secondDividendUserId={}, secondDividendMoney={}", order.getOrderNo(), shopRoleReferees.get(0), storeDirectMoney, shopRoleReferees.get(1), storeSimpleMoney); - creditDealerCommission(shopRoleReferees.get(0), storeDirectMoney, order, order.getUserId(), "门店直推佣金(type=1,第1个,2%)"); - creditDealerCommission(shopRoleReferees.get(1), storeSimpleMoney, order, order.getUserId(), "门店简推佣金(type=1,第2个,1%)"); + creditDealerCommission(shopRoleReferees.get(0), storeDirectMoney, order, order.getUserId(), "门店直推佣金(第1级,2%)"); + creditDealerCommission(shopRoleReferees.get(1), storeSimpleMoney, order, order.getUserId(), "门店简推佣金(第2级,1%)"); return new ShopRoleCommission(shopRoleReferees.get(0), storeDirectMoney, shopRoleReferees.get(1), storeSimpleMoney); } - private List findFirstTwoShopRoleRefereesByDealerReferee(Integer buyerUserId) { + /** + * 沿 shop_dealer_referee(level=1) 链路向上找到最近两级上级。 + *

+ * 旧逻辑依赖扩展字段 isShopRole(已废弃) 来过滤门店角色;目前按链路取前两级,保证能回填/结算。 + */ + private List findFirstTwoUpstreamReferees(Integer buyerUserId) { if (buyerUserId == null) { return Collections.emptyList(); } @@ -232,47 +234,23 @@ public class DealerOrderSettlement10584Task { List result = new ArrayList<>(2); Set visited = new HashSet<>(); - // 优先:直接从该买家(userId)的多级关系(level=1/2/3/...)里,按 level 升序找到最近的两级门店(type=1)。 - // 背景:部分数据只维护“买家 -> 上级们”的多级(level)记录,但不一定维护“上级 -> 更上级”的记录; - // 若仅做链路向上查找,会导致门店直推/简推无法命中,收益与资金明细都不会写入。 - // 注意:isShopRole 为扩展字段(非表字段),由自定义SQL按 ShopDealerUser.type=1 计算带出。 - List relList = shopDealerRefereeMapper.selectRefereeChainWithShopRole( - TENANT_ID, buyerUserId, MAX_REFEREE_CHAIN_DEPTH - ); - for (ShopDealerReferee rel : relList) { - Integer dealerId = rel != null ? rel.getDealerId() : null; - if (dealerId == null || !visited.add(dealerId)) { - continue; - } - if (Boolean.TRUE.equals(rel.getIsShopRole())) { - result.add(dealerId); - if (result.size() >= 2) { - return result; - } - } - } - - // 兜底:若只维护了 level=1 的推荐关系,则尝试按“查两次/多次”的方式一路向上找门店(type=1)。 + // 仅依赖 level=1 的推荐关系一路向上查找(兼容“只维护 level=1”的数据形态)。 Integer current = buyerUserId; for (int i = 0; i < MAX_REFEREE_CHAIN_DEPTH && current != null; i++) { - ShopDealerReferee parentRel = shopDealerRefereeMapper.selectFirstLevelRefereeWithShopRole(TENANT_ID, current); - Integer parentId = parentRel != null ? parentRel.getDealerId() : null; + Integer parentId = getDealerRefereeId(current, 1); if (parentId == null) { break; } - log.debug("门店(type=1)链路向上 - buyerOrChildUserId={}, parentId={}", current, parentId); + log.debug("分红链路向上 - buyerOrChildUserId={}, parentId={}", current, parentId); if (!visited.add(parentId)) { break; } - if (parentRel != null && Boolean.TRUE.equals(parentRel.getIsShopRole())) { - log.debug("门店(type=1)命中 - parentId={}", parentId); - result.add(parentId); - if (result.size() >= 2) { - break; - } + result.add(parentId); + if (result.size() >= 2) { + break; } current = parentId; @@ -407,15 +385,33 @@ public class DealerOrderSettlement10584Task { .eq(ShopDealerOrder::getTenantId, TENANT_ID) .eq(ShopDealerOrder::getOrderNo, order.getOrderNo()); boolean needUpdate = false; - if (existed.getFirstDividendUser() == null && shopRoleCommission.storeDirectUserId != null) { - uw.set(ShopDealerOrder::getFirstDividendUser, shopRoleCommission.storeDirectUserId); - uw.set(ShopDealerOrder::getFirstDividend, shopRoleCommission.storeDirectMoney); - needUpdate = true; + if (shopRoleCommission.storeDirectUserId != null) { + Integer existedUser = existed.getFirstDividendUser(); + boolean needSetUser = existedUser == null; + boolean needSetMoney = existed.getFirstDividend() == null || existed.getFirstDividend().signum() == 0; + if (needSetUser) { + uw.set(ShopDealerOrder::getFirstDividendUser, shopRoleCommission.storeDirectUserId); + needUpdate = true; + } + boolean sameUser = existedUser == null || Objects.equals(existedUser, shopRoleCommission.storeDirectUserId); + if (sameUser && needSetMoney && shopRoleCommission.storeDirectMoney != null && shopRoleCommission.storeDirectMoney.signum() > 0) { + uw.set(ShopDealerOrder::getFirstDividend, shopRoleCommission.storeDirectMoney); + needUpdate = true; + } } - if (existed.getSecondDividendUser() == null && shopRoleCommission.storeSimpleUserId != null) { - uw.set(ShopDealerOrder::getSecondDividendUser, shopRoleCommission.storeSimpleUserId); - uw.set(ShopDealerOrder::getSecondDividend, shopRoleCommission.storeSimpleMoney); - needUpdate = true; + if (shopRoleCommission.storeSimpleUserId != null) { + Integer existedUser = existed.getSecondDividendUser(); + boolean needSetUser = existedUser == null; + boolean needSetMoney = existed.getSecondDividend() == null || existed.getSecondDividend().signum() == 0; + if (needSetUser) { + uw.set(ShopDealerOrder::getSecondDividendUser, shopRoleCommission.storeSimpleUserId); + needUpdate = true; + } + boolean sameUser = existedUser == null || Objects.equals(existedUser, shopRoleCommission.storeSimpleUserId); + if (sameUser && needSetMoney && shopRoleCommission.storeSimpleMoney != null && shopRoleCommission.storeSimpleMoney.signum() > 0) { + uw.set(ShopDealerOrder::getSecondDividend, shopRoleCommission.storeSimpleMoney); + needUpdate = true; + } } if (needUpdate) { shopDealerOrderService.update(uw); @@ -479,6 +475,13 @@ public class DealerOrderSettlement10584Task { return base.multiply(rate).setScale(2, RoundingMode.HALF_UP); } + private BigDecimal calcDividendMoney(BigDecimal base, BigDecimal rate) { + if (base == null || rate == null) { + return BigDecimal.ZERO; + } + return base.multiply(rate).setScale(DIVIDEND_SCALE, RoundingMode.HALF_UP); + } + private static class DealerRefereeCommission { private final Integer directDealerId; private final BigDecimal directMoney; diff --git a/src/main/java/com/gxwebsoft/shop/task/ShopOrderSettlement10584Task.java b/src/main/java/com/gxwebsoft/shop/task/ShopOrderSettlement10584Task.java new file mode 100644 index 0000000..ae1afed --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/task/ShopOrderSettlement10584Task.java @@ -0,0 +1,234 @@ +package com.gxwebsoft.shop.task; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.gxwebsoft.common.core.context.TenantContext; +import com.gxwebsoft.shop.entity.ShopDealerReferee; +import com.gxwebsoft.shop.entity.ShopDealerUser; +import com.gxwebsoft.shop.entity.ShopOrder; +import com.gxwebsoft.shop.mapper.ShopDealerRefereeMapper; +import com.gxwebsoft.shop.service.ShopDealerRefereeService; +import com.gxwebsoft.shop.service.ShopDealerUserService; +import com.gxwebsoft.shop.service.ShopOrderService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * 租户10584:一次性排查任务 + *

+ * 应用启动后延迟10秒执行一次:查询指定订单的下单用户上级推荐人/门店(type=1)链路。 + */ +@Slf4j +@Component +public class ShopOrderSettlement10584Task { + + private static final Integer TENANT_ID = 10584; + + /** + * 目标订单编号(按用户要求写死;如需动态,可改成配置项或入参)。 + */ + private static final String TARGET_ORDER_NO = "2015591043920007168"; + + private static final int MAX_REFEREE_CHAIN_DEPTH = 20; + + private final AtomicBoolean executed = new AtomicBoolean(false); + + @Resource + private ShopOrderService shopOrderService; + + @Resource + private ShopDealerRefereeService shopDealerRefereeService; + + @Resource + private ShopDealerRefereeMapper shopDealerRefereeMapper; + + @Resource + private ShopDealerUserService shopDealerUserService; + + /** + * 启动10秒后执行,只执行一次。 + */ + @EventListener(ApplicationReadyEvent.class) + public void scheduleOnceAfterStartup() { + log.info("ShopOrderSettlement10584Task 已注册:10秒后执行一次 - tenantId={}, orderNo={}", TENANT_ID, TARGET_ORDER_NO); + CompletableFuture + .delayedExecutor(10, TimeUnit.SECONDS) + .execute(() -> TenantContext.runIgnoreTenant(this::runOnceIgnoreTenant)); + } + + private void runOnceIgnoreTenant() { + if (!executed.compareAndSet(false, true)) { + return; + } + + ShopOrder order = shopOrderService.getOne( + new LambdaQueryWrapper() + .eq(ShopOrder::getTenantId, TENANT_ID) + .eq(ShopOrder::getOrderNo, TARGET_ORDER_NO) + .eq(ShopOrder::getDeleted, 0) + .orderByDesc(ShopOrder::getOrderId) + .last("limit 1") + ); + if (order == null) { + log.warn("未找到目标订单 - tenantId={}, orderNo={}", TENANT_ID, TARGET_ORDER_NO); + return; + } + + Integer buyerUserId = order.getUserId(); + Integer refereeId = getRefereeIdByLevel(buyerUserId, 1); + Integer refereeRefereeId = getRefereeIdByLevel(buyerUserId, 2); + + List upstreamReferees = findFirstTwoUpstreamReferees(buyerUserId); + Integer upstreamRefereeId = upstreamReferees.size() > 0 ? upstreamReferees.get(0) : null; + Integer upstreamRefereeRefereeId = upstreamReferees.size() > 1 ? upstreamReferees.get(1) : null; + + List shopRoleReferees = findFirstTwoShopRoleReferees(buyerUserId); + Integer shopRoleRefereeId = shopRoleReferees.size() > 0 ? shopRoleReferees.get(0) : null; + Integer shopRoleRefereeRefereeId = shopRoleReferees.size() > 1 ? shopRoleReferees.get(1) : null; + + log.info("订单推荐关系查询结果 - orderNo={}, buyerUserId={}, refereeId(level=1)={}, refereeRefereeId(level=2)={}, upstreamRefereeId(level=1链路第1级)={}, upstreamRefereeRefereeId(level=1链路第2级)={}, shopRoleRefereeId(type=1)={}, shopRoleRefereeRefereeId(type=1)={}", + order.getOrderNo(), buyerUserId, refereeId, refereeRefereeId, upstreamRefereeId, upstreamRefereeRefereeId, shopRoleRefereeId, shopRoleRefereeRefereeId); + + // 便于排查:从下单用户开始一路向上打印每一跳的门店(type=1)判定情况。 + logShopRoleTraversal(buyerUserId); + } + + private Integer getRefereeIdByLevel(Integer userId, int level) { + if (userId == null) { + return null; + } + ShopDealerReferee rel = shopDealerRefereeService.getOne( + new LambdaQueryWrapper() + .eq(ShopDealerReferee::getTenantId, TENANT_ID) + .eq(ShopDealerReferee::getUserId, userId) + .eq(ShopDealerReferee::getLevel, level) + .orderByDesc(ShopDealerReferee::getId) + .last("limit 1") + ); + return rel != null ? rel.getDealerId() : null; + } + + /** + * 基于 shop_dealer_referee(level=1) 的链路,找出“最近的两级上级用户”。 + *

+ * 旧逻辑依赖扩展字段 isShopRole(已废弃) 过滤门店角色;目前仅按链路取前两级用于排查。 + */ + private List findFirstTwoUpstreamReferees(Integer buyerUserId) { + if (buyerUserId == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(2); + Set visited = new HashSet<>(); + + // 仅依赖 level=1 的推荐关系一路向上查找(可兼容“只维护 level=1”的数据形态)。 + Integer current = buyerUserId; + for (int i = 0; i < MAX_REFEREE_CHAIN_DEPTH && current != null && result.size() < 2; i++) { + Integer parentId = getRefereeIdByLevel(current, 1); + if (parentId == null || !visited.add(parentId)) { + break; + } + + result.add(parentId); + current = parentId; + } + + return result; + } + + /** + * 基于 shop_dealer_referee 的链路,找出“最近的两级门店角色用户”(ShopDealerUser.type=1)。 + *

+ * 判定逻辑由 SQL join shop_dealer_user(type=1) 得到 isShopRole。 + */ + private List findFirstTwoShopRoleReferees(Integer buyerUserId) { + if (buyerUserId == null) { + return Collections.emptyList(); + } + + List result = new ArrayList<>(2); + Set visited = new HashSet<>(); + + // 优先:直接从该买家(userId)的多级关系(level=1/2/3/...)里,按 level 升序找到最近的两级门店(type=1)。 +// List relList = shopDealerRefereeMapper.selectRefereeChainWithShopRole( +// TENANT_ID, buyerUserId, MAX_REFEREE_CHAIN_DEPTH +// ); +// for (ShopDealerReferee rel : relList) { +// Integer dealerId = rel != null ? rel.getDealerId() : null; +// if (dealerId == null || !visited.add(dealerId)) { +// continue; +// } +// if (Boolean.TRUE.equals(rel.getIsShopRole())) { +// result.add(dealerId); +// if (result.size() >= 2) { +// return result; +// } +// } +// } + + // 兜底:若只维护了 level=1 的推荐关系,则尝试按“向上查找”的方式一路找门店(type=1)。 +// Integer current = buyerUserId; +// for (int i = 0; i < MAX_REFEREE_CHAIN_DEPTH && current != null && result.size() < 2; i++) { +// ShopDealerReferee parentRel = shopDealerRefereeMapper.selectFirstLevelRefereeWithShopRole(TENANT_ID, current); +// Integer parentId = parentRel != null ? parentRel.getDealerId() : null; +// if (parentId == null || !visited.add(parentId)) { +// break; +// } +// +// if (Boolean.TRUE.equals(parentRel.getIsShopRole())) { +// result.add(parentId); +// } +// current = parentId; +// } +// + return result; + } + + private void logShopRoleTraversal(Integer buyerUserId) { + if (buyerUserId == null) { + return; + } + + Integer current = buyerUserId; + Set visited = new HashSet<>(); + /*for (int depth = 1; depth <= MAX_REFEREE_CHAIN_DEPTH && current != null; depth++) { + ShopDealerReferee parentRel = shopDealerRefereeMapper.selectFirstLevelRefereeWithShopRole(TENANT_ID, current); + Integer parentId = parentRel != null ? parentRel.getDealerId() : null; + if (parentId == null) { + log.info("type=1链路检查结束 - buyerUserId={}, depth={}, currentUserId={}, reason=no_parent", buyerUserId, depth, current); + return; + } + if (!visited.add(parentId)) { + log.info("type=1链路检查结束 - buyerUserId={}, depth={}, currentUserId={}, parentUserId={}, reason=cycle", buyerUserId, depth, current, parentId); + return; + } + + ShopDealerUser du = shopDealerUserService.getOne( + new LambdaQueryWrapper() + .eq(ShopDealerUser::getTenantId, TENANT_ID) + .eq(ShopDealerUser::getUserId, parentId) + .orderByDesc(ShopDealerUser::getId) + .last("limit 1") + ); + Integer duType = du != null ? du.getType() : null; + Integer duIsDelete = du != null ? du.getIsDelete() : null; + + log.info("type=1链路检查 - buyerUserId={}, depth={}, childUserId={}, parentUserId={}, isShopRole(sql)={}, shopDealerUser.type={}, shopDealerUser.is_delete={}", + buyerUserId, depth, current, parentId, parentRel != null ? parentRel.getIsShopRole() : null, duType, duIsDelete); + + current = parentId; + }*/ + log.info("type=1链路检查结束 - buyerUserId={}, depthReached={}, reason=max_depth", buyerUserId, MAX_REFEREE_CHAIN_DEPTH); + } +}