部门交易金额
This commit is contained in:
@@ -761,6 +761,170 @@ public class LbDepartmentUserServiceImpl extends ServiceImpl<LbDepartmentUserMap
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getDepartmentUserTreeCopy(String tenantId, Integer isActive, LocalDate joinDate, LocalDate lastTradeDate,
|
||||
String buyStartTime, String buyEndTime) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "租户id不能为空");
|
||||
return result;
|
||||
}
|
||||
String tenantIdTrim = tenantId.trim();
|
||||
|
||||
List<LbUser> lbUsers = lbUserMapper.selectList(
|
||||
new LambdaQueryWrapper<LbUser>().eq(LbUser::getTenantId, tenantIdTrim));
|
||||
if (lbUsers == null || lbUsers.isEmpty()) {
|
||||
result.put("success", true);
|
||||
result.put("message", "查询成功");
|
||||
result.put("data", new ArrayList<>());
|
||||
result.put("total", 0);
|
||||
result.put("tenantId", tenantIdTrim);
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, LbUser> userById = new LinkedHashMap<>();
|
||||
for (LbUser lbUser : lbUsers) {
|
||||
if (lbUser.getId() != null) {
|
||||
userById.put(String.valueOf(lbUser.getId()), lbUser);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, LbBuyerTradeStats> tradeStatsByUserId = loadBuyerTradeStatsFromOrderRow(tenantIdTrim);
|
||||
boolean hasFilter = isActive != null || joinDate != null || lastTradeDate != null;
|
||||
|
||||
Set<String> matchedUserIds = new HashSet<>();
|
||||
Map<String, LocalDate> joinDateByUserId = new HashMap<>();
|
||||
Map<String, LocalDate> lastTradeDateByUserId = new HashMap<>();
|
||||
Map<String, BigDecimal> lastBuyAmtByUserId = new HashMap<>();
|
||||
Map<String, Integer> isActiveByUserId = new HashMap<>();
|
||||
for (LbUser lbUser : lbUsers) {
|
||||
if (lbUser.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
String userId = String.valueOf(lbUser.getId());
|
||||
LocalDate userJoinDate = lbUser.getJoinTime() != null
|
||||
? lbUser.getJoinTime().toLocalDate() : null;
|
||||
LbBuyerTradeStats tradeStats = tradeStatsByUserId.get(userId);
|
||||
LocalDate userLastTradeDate = tradeStats == null
|
||||
? null : parseOrderTimeToDate(tradeStats.getPayTime());
|
||||
BigDecimal userLastBuyAmt = tradeStats == null ? null : tradeStats.getTotalMoney();
|
||||
int userIsActive = tradeStats == null ? 0 : 1;
|
||||
|
||||
joinDateByUserId.put(userId, userJoinDate);
|
||||
lastTradeDateByUserId.put(userId, userLastTradeDate);
|
||||
lastBuyAmtByUserId.put(userId, userLastBuyAmt);
|
||||
isActiveByUserId.put(userId, userIsActive);
|
||||
|
||||
if (!hasFilter || matchesTreeFilter(
|
||||
userIsActive, userJoinDate, userLastTradeDate, isActive, joinDate, lastTradeDate)) {
|
||||
matchedUserIds.add(userId);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> visibleUserIds = hasFilter
|
||||
? includeAncestorUserIds(matchedUserIds, userById)
|
||||
: new HashSet<>(userById.keySet());
|
||||
|
||||
Map<String, Map<String, Object>> nodeByUserId = new LinkedHashMap<>();
|
||||
Map<String, String> parentByUserId = new HashMap<>();
|
||||
Map<String, List<String>> childrenByUserId = new HashMap<>();
|
||||
|
||||
for (String userId : visibleUserIds) {
|
||||
LbUser lbUser = userById.get(userId);
|
||||
if (lbUser == null) {
|
||||
continue;
|
||||
}
|
||||
nodeByUserId.put(userId, toLbUserTreeNode(
|
||||
lbUser,
|
||||
joinDateByUserId.get(userId),
|
||||
lastTradeDateByUserId.get(userId),
|
||||
lastBuyAmtByUserId.get(userId),
|
||||
isActiveByUserId.getOrDefault(userId, 0)));
|
||||
|
||||
String parentUserId = resolveLbUserParentId(lbUser, userById);
|
||||
if (parentUserId != null && visibleUserIds.contains(parentUserId)) {
|
||||
parentByUserId.put(userId, parentUserId);
|
||||
childrenByUserId.computeIfAbsent(parentUserId, k -> new ArrayList<>()).add(userId);
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasTradeTimeFilter = (buyStartTime != null && !buyStartTime.trim().isEmpty())
|
||||
|| (buyEndTime != null && !buyEndTime.trim().isEmpty());
|
||||
|
||||
Map<String, BigDecimal> tradeMoneySumByUserId = new HashMap<>();
|
||||
Map<String, BigDecimal> userTradeMoney = new HashMap<>();
|
||||
if (hasTradeTimeFilter) {
|
||||
if (!visibleUserIds.isEmpty()) {
|
||||
List<Map<String, Object>> tradeResults = lbOrderRowMapper.selectSumTotalMoneyGroupByBuyerIds(
|
||||
tenantIdTrim, new ArrayList<>(visibleUserIds), buyStartTime, buyEndTime);
|
||||
|
||||
for (Map<String, Object> row : tradeResults) {
|
||||
String buyerId = String.valueOf(row.get("buyerId"));
|
||||
BigDecimal totalMoney = (BigDecimal) row.get("totalMoney");
|
||||
userTradeMoney.put(buyerId, totalMoney != null ? totalMoney : BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
for (String userId : visibleUserIds) {
|
||||
BigDecimal sumAmount = calculateRecursiveTradeSumOptimized(userId, childrenByUserId, userTradeMoney);
|
||||
tradeMoneySumByUserId.put(userId, sumAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, Object>> treeRoots = new ArrayList<>();
|
||||
for (Map.Entry<String, Map<String, Object>> entry : nodeByUserId.entrySet()) {
|
||||
String userId = entry.getKey();
|
||||
Map<String, Object> node = entry.getValue();
|
||||
|
||||
if (hasTradeTimeFilter) {
|
||||
node.put("selfTradeMoney", userTradeMoney.getOrDefault(userId, BigDecimal.ZERO));
|
||||
node.put("tradeMoneySum", tradeMoneySumByUserId.getOrDefault(userId, BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
String parentUserId = parentByUserId.get(userId);
|
||||
Map<String, Object> parentNode = parentUserId == null ? null : nodeByUserId.get(parentUserId);
|
||||
if (parentNode == null) {
|
||||
treeRoots.add(node);
|
||||
continue;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> children = (List<Map<String, Object>>) parentNode.get("children");
|
||||
children.add(node);
|
||||
}
|
||||
sortDepartmentUserTreeByName(treeRoots);
|
||||
List<Map<String, Object>> treeData = skipFirstTreeLevel(treeRoots);
|
||||
|
||||
result.put("success", true);
|
||||
result.put("message", "查询成功");
|
||||
result.put("data", treeData);
|
||||
result.put("total", countTreeNodes(treeData));
|
||||
result.put("tenantId", tenantIdTrim);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
result.put("success", false);
|
||||
result.put("message", "查询树形结构异常:" + e.getMessage());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 优化后的递归计算:从内存 Map 中获取数据,避免重复数据库查询
|
||||
*/
|
||||
private BigDecimal calculateRecursiveTradeSumOptimized(String userId, Map<String, List<String>> childrenByUserId,
|
||||
Map<String, BigDecimal> userTradeMoney) {
|
||||
BigDecimal sum = userTradeMoney.getOrDefault(userId, BigDecimal.ZERO);
|
||||
|
||||
List<String> children = childrenByUserId.get(userId);
|
||||
if (children != null && !children.isEmpty()) {
|
||||
for (String childId : children) {
|
||||
sum = sum.add(calculateRecursiveTradeSumOptimized(childId, childrenByUserId, userTradeMoney));
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉第 1 级根节点,将其 children 提升为返回给前端的顶层。
|
||||
*/
|
||||
@@ -1135,6 +1299,153 @@ public class LbDepartmentUserServiceImpl extends ServiceImpl<LbDepartmentUserMap
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getDepartmentUserTreeSumTotalMoney(String tenantId, Integer isActive, LocalDate joinDate, LocalDate lastTradeDate, String buyStartTime, String buyEndTime) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
try {
|
||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "租户id不能为空");
|
||||
return result;
|
||||
}
|
||||
String tenantIdTrim = tenantId.trim();
|
||||
|
||||
List<LbUser> lbUsers = lbUserMapper.selectList(
|
||||
new LambdaQueryWrapper<LbUser>().eq(LbUser::getTenantId, tenantIdTrim));
|
||||
if (lbUsers == null || lbUsers.isEmpty()) {
|
||||
result.put("success", true);
|
||||
result.put("message", "查询成功");
|
||||
result.put("data", new ArrayList<>());
|
||||
result.put("total", 0);
|
||||
result.put("tenantId", tenantIdTrim);
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, LbUser> userById = new LinkedHashMap<>();
|
||||
for (LbUser lbUser : lbUsers) {
|
||||
if (lbUser.getId() != null) {
|
||||
userById.put(String.valueOf(lbUser.getId()), lbUser);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, LbBuyerTradeStats> tradeStatsByUserId = loadBuyerTradeStatsFromOrderRow(tenantIdTrim);
|
||||
boolean hasFilter = isActive != null || joinDate != null || lastTradeDate != null;
|
||||
|
||||
Set<String> matchedUserIds = new HashSet<>();
|
||||
Map<String, LocalDate> joinDateByUserId = new HashMap<>();
|
||||
Map<String, LocalDate> lastTradeDateByUserId = new HashMap<>();
|
||||
Map<String, BigDecimal> lastBuyAmtByUserId = new HashMap<>();
|
||||
Map<String, Integer> isActiveByUserId = new HashMap<>();
|
||||
for (LbUser lbUser : lbUsers) {
|
||||
if (lbUser.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
String userId = String.valueOf(lbUser.getId());
|
||||
LocalDate userJoinDate = lbUser.getJoinTime() != null
|
||||
? lbUser.getJoinTime().toLocalDate() : null;
|
||||
LbBuyerTradeStats tradeStats = tradeStatsByUserId.get(userId);
|
||||
LocalDate userLastTradeDate = tradeStats == null
|
||||
? null : parseOrderTimeToDate(tradeStats.getPayTime());
|
||||
BigDecimal userLastBuyAmt = tradeStats == null ? null : tradeStats.getTotalMoney();
|
||||
int userIsActive = tradeStats == null ? 0 : 1;
|
||||
|
||||
joinDateByUserId.put(userId, userJoinDate);
|
||||
lastTradeDateByUserId.put(userId, userLastTradeDate);
|
||||
lastBuyAmtByUserId.put(userId, userLastBuyAmt);
|
||||
isActiveByUserId.put(userId, userIsActive);
|
||||
|
||||
if (!hasFilter || matchesTreeFilter(
|
||||
userIsActive, userJoinDate, userLastTradeDate, isActive, joinDate, lastTradeDate)) {
|
||||
matchedUserIds.add(userId);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> visibleUserIds = hasFilter
|
||||
? includeAncestorUserIds(matchedUserIds, userById)
|
||||
: new HashSet<>(userById.keySet());
|
||||
|
||||
Map<String, Map<String, Object>> nodeByUserId = new LinkedHashMap<>();
|
||||
Map<String, String> parentByUserId = new HashMap<>();
|
||||
Map<String, List<String>> childrenByUserId = new HashMap<>();
|
||||
|
||||
for (String userId : visibleUserIds) {
|
||||
LbUser lbUser = userById.get(userId);
|
||||
if (lbUser == null) {
|
||||
continue;
|
||||
}
|
||||
nodeByUserId.put(userId, toLbUserTreeNode(
|
||||
lbUser,
|
||||
joinDateByUserId.get(userId),
|
||||
lastTradeDateByUserId.get(userId),
|
||||
lastBuyAmtByUserId.get(userId),
|
||||
isActiveByUserId.getOrDefault(userId, 0)));
|
||||
|
||||
String parentUserId = resolveLbUserParentId(lbUser, userById);
|
||||
if (parentUserId != null && visibleUserIds.contains(parentUserId)) {
|
||||
parentByUserId.put(userId, parentUserId);
|
||||
childrenByUserId.computeIfAbsent(parentUserId, k -> new ArrayList<>()).add(userId);
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasTradeTimeFilter = (buyStartTime != null && !buyStartTime.trim().isEmpty())
|
||||
|| (buyEndTime != null && !buyEndTime.trim().isEmpty());
|
||||
|
||||
Map<String, BigDecimal> tradeMoneySumByUserId = new HashMap<>();
|
||||
Map<String, BigDecimal> userTradeMoney = new HashMap<>();
|
||||
if (hasTradeTimeFilter) {
|
||||
if (!visibleUserIds.isEmpty()) {
|
||||
List<Map<String, Object>> tradeResults = lbOrderRowMapper.selectSumTotalMoneyGroupByBuyerIds(
|
||||
tenantIdTrim, new ArrayList<>(visibleUserIds), buyStartTime, buyEndTime);
|
||||
|
||||
for (Map<String, Object> row : tradeResults) {
|
||||
String buyerId = String.valueOf(row.get("buyerId"));
|
||||
BigDecimal totalMoney = (BigDecimal) row.get("totalMoney");
|
||||
userTradeMoney.put(buyerId, totalMoney != null ? totalMoney : BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
for (String userId : visibleUserIds) {
|
||||
BigDecimal sumAmount = calculateRecursiveTradeSumOptimized(userId, childrenByUserId, userTradeMoney);
|
||||
tradeMoneySumByUserId.put(userId, sumAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Map<String, Object>> treeRoots = new ArrayList<>();
|
||||
for (Map.Entry<String, Map<String, Object>> entry : nodeByUserId.entrySet()) {
|
||||
String userId = entry.getKey();
|
||||
Map<String, Object> node = entry.getValue();
|
||||
|
||||
if (hasTradeTimeFilter) {
|
||||
node.put("selfTradeMoney", userTradeMoney.getOrDefault(userId, BigDecimal.ZERO));
|
||||
node.put("tradeMoneySum", tradeMoneySumByUserId.getOrDefault(userId, BigDecimal.ZERO));
|
||||
}
|
||||
|
||||
String parentUserId = parentByUserId.get(userId);
|
||||
Map<String, Object> parentNode = parentUserId == null ? null : nodeByUserId.get(parentUserId);
|
||||
if (parentNode == null) {
|
||||
treeRoots.add(node);
|
||||
continue;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> children = (List<Map<String, Object>>) parentNode.get("children");
|
||||
children.add(node);
|
||||
}
|
||||
sortDepartmentUserTreeByName(treeRoots);
|
||||
List<Map<String, Object>> treeData = skipFirstTreeLevel(treeRoots);
|
||||
|
||||
result.put("success", true);
|
||||
result.put("message", "查询成功");
|
||||
result.put("data", treeData);
|
||||
result.put("total", countTreeNodes(treeData));
|
||||
result.put("tenantId", tenantIdTrim);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
result.put("success", false);
|
||||
result.put("message", "查询树形结构异常:" + e.getMessage());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class OrderBuyStats {
|
||||
private String earliestBuyTime;
|
||||
private LocalDateTime earliestBuyDateTime;
|
||||
|
||||
Reference in New Issue
Block a user