统计交易金额
This commit is contained in:
@@ -13,4 +13,10 @@ import java.util.Map;
|
||||
*/
|
||||
public interface ILbDailyUserTradeReportService extends IService<LbDailyUserTradeReport> {
|
||||
Map<String, Object> calculateReportSumByDateAndTenant(LocalDate reportDate, String tenantId);
|
||||
|
||||
/**
|
||||
* 按日期范围与租户统计每人四类金额(昨日买入、当日卖出、当日买入、差额):本人汇总与递归下级汇总。
|
||||
*/
|
||||
Map<String, Object> listUserTradeAmountWithTeamByDateRangeAndTenant(
|
||||
LocalDate startDate, LocalDate endDate, String tenantId);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,24 @@ package com.rj.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.rj.entity.LbDailyUserTradeReport;
|
||||
import com.rj.entity.LbDepartmentUser;
|
||||
import com.rj.mapper.LbDailyUserTradeReportMapper;
|
||||
import com.rj.service.ILbDailyUserTradeReportService;
|
||||
import com.rj.service.ILbDepartmentUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -25,6 +34,9 @@ public class LbDailyUserTradeReportServiceImpl extends ServiceImpl<LbDailyUserTr
|
||||
|
||||
private static final String DATA_TYPE_REPORT_SUM = "report_sum";
|
||||
|
||||
@Autowired
|
||||
private ILbDepartmentUserService lbDepartmentUserService;
|
||||
|
||||
@Override
|
||||
public Map<String, Object> calculateReportSumByDateAndTenant(LocalDate reportDate, String tenantId) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
@@ -81,7 +93,206 @@ public class LbDailyUserTradeReportServiceImpl extends ServiceImpl<LbDailyUserTr
|
||||
return result;
|
||||
}
|
||||
|
||||
private BigDecimal defaultZero(BigDecimal value) {
|
||||
private static BigDecimal defaultZero(BigDecimal value) {
|
||||
return value == null ? BigDecimal.ZERO : value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> listUserTradeAmountWithTeamByDateRangeAndTenant(
|
||||
LocalDate startDate, LocalDate endDate, String tenantId) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (tenantId == null || tenantId.trim().isEmpty()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "tenantId不能为空");
|
||||
return result;
|
||||
}
|
||||
if (startDate == null || endDate == null) {
|
||||
result.put("success", false);
|
||||
result.put("message", "开始日期和结束日期不能为空");
|
||||
return result;
|
||||
}
|
||||
if (endDate.isBefore(startDate)) {
|
||||
result.put("success", false);
|
||||
result.put("message", "结束日期不能早于开始日期");
|
||||
return result;
|
||||
}
|
||||
|
||||
String tenantIdTrim = tenantId.trim();
|
||||
LocalDateTime rangeStart = startDate.atStartOfDay();
|
||||
LocalDateTime rangeEnd = endDate.atTime(23, 59, 59);
|
||||
|
||||
List<LbDepartmentUser> deptUsers = lbDepartmentUserService.list(
|
||||
new LambdaQueryWrapper<LbDepartmentUser>()
|
||||
.eq(LbDepartmentUser::getTenantId, tenantIdTrim));
|
||||
if (deptUsers == null || deptUsers.isEmpty()) {
|
||||
result.put("success", true);
|
||||
result.put("message", "查询成功");
|
||||
result.put("data", List.of());
|
||||
result.put("total", 0);
|
||||
result.put("startDate", startDate);
|
||||
result.put("endDate", endDate);
|
||||
result.put("tenantId", tenantIdTrim);
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<String, String> userIdToName = new HashMap<>();
|
||||
Set<String> tenantUserIds = new HashSet<>();
|
||||
Map<String, List<String>> childrenByParentUserId = new HashMap<>();
|
||||
for (LbDepartmentUser row : deptUsers) {
|
||||
if (row.getUserId() == null || row.getUserId().trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String uid = row.getUserId().trim();
|
||||
tenantUserIds.add(uid);
|
||||
if (row.getName() != null && !row.getName().trim().isEmpty()) {
|
||||
userIdToName.putIfAbsent(uid, row.getName().trim());
|
||||
}
|
||||
String parentUserId = row.getParentId() == null ? null : row.getParentId().trim();
|
||||
if (parentUserId != null && !parentUserId.isEmpty()) {
|
||||
List<String> ch = childrenByParentUserId.computeIfAbsent(parentUserId, k -> new ArrayList<>());
|
||||
if (!ch.contains(uid)) {
|
||||
ch.add(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (List<String> list : childrenByParentUserId.values()) {
|
||||
list.sort(String::compareTo);
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<LbDailyUserTradeReport> tradeQw = new LambdaQueryWrapper<>();
|
||||
tradeQw.eq(LbDailyUserTradeReport::getTenantId, tenantIdTrim)
|
||||
.ge(LbDailyUserTradeReport::getReportDate, rangeStart)
|
||||
.le(LbDailyUserTradeReport::getReportDate, rangeEnd)
|
||||
.ne(LbDailyUserTradeReport::getDataType, DATA_TYPE_REPORT_SUM);
|
||||
|
||||
Map<String, TradeAmtBundle> ownAmtByUserId = new HashMap<>();
|
||||
for (LbDailyUserTradeReport r : list(tradeQw)) {
|
||||
if (r.getUserId() == null || r.getUserId().trim().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String uid = r.getUserId().trim();
|
||||
ownAmtByUserId
|
||||
.computeIfAbsent(uid, k -> TradeAmtBundle.zeros())
|
||||
.addFromReportRow(r);
|
||||
if (r.getNickname() != null && !r.getNickname().trim().isEmpty()) {
|
||||
userIdToName.putIfAbsent(uid, r.getNickname().trim());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, TradeAmtBundle> teamAmtMemo = new HashMap<>();
|
||||
for (String userId : tenantUserIds) {
|
||||
teamAmtRecursive(userId, childrenByParentUserId, ownAmtByUserId, teamAmtMemo, new HashSet<>());
|
||||
}
|
||||
|
||||
List<Map<String, Object>> rows = new ArrayList<>();
|
||||
for (String userId : tenantUserIds) {
|
||||
TradeAmtBundle own = ownAmt(userId, ownAmtByUserId);
|
||||
TradeAmtBundle team = teamAmt(userId, teamAmtMemo);
|
||||
TradeAmtBundle total = own.addCopy(team);
|
||||
Map<String, Object> row = new LinkedHashMap<>();
|
||||
row.put("userId", userId);
|
||||
row.put("name", userIdToName.getOrDefault(userId, ""));
|
||||
row.put("ownYestodayBuyAmt", own.yestodayBuyAmt);
|
||||
row.put("teamYestodayBuyAmt", team.yestodayBuyAmt);
|
||||
row.put("totalYestodayBuyAmt", total.yestodayBuyAmt);
|
||||
row.put("ownDailySellAmt", own.dailySellAmt);
|
||||
row.put("teamDailySellAmt", team.dailySellAmt);
|
||||
row.put("totalDailySellAmt", total.dailySellAmt);
|
||||
row.put("ownDailyBuyAmt", own.dailyBuyAmt);
|
||||
row.put("teamDailyBuyAmt", team.dailyBuyAmt);
|
||||
row.put("totalDailyBuyAmt", total.dailyBuyAmt);
|
||||
row.put("ownDiffAmt", own.diffAmt);
|
||||
row.put("teamDiffAmt", team.diffAmt);
|
||||
row.put("totalDiffAmt", total.diffAmt);
|
||||
rows.add(row);
|
||||
}
|
||||
rows.sort(Comparator.comparing((Map<String, Object> m) -> (BigDecimal) m.get("totalDiffAmt")).reversed());
|
||||
|
||||
result.put("success", true);
|
||||
result.put("message", "查询成功");
|
||||
result.put("data", rows);
|
||||
result.put("total", rows.size());
|
||||
result.put("startDate", startDate);
|
||||
result.put("endDate", endDate);
|
||||
result.put("tenantId", tenantIdTrim);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static TradeAmtBundle ownAmt(String userId, Map<String, TradeAmtBundle> ownAmtByUserId) {
|
||||
TradeAmtBundle b = ownAmtByUserId.get(userId);
|
||||
return b != null ? b : TradeAmtBundle.zeros();
|
||||
}
|
||||
|
||||
private static TradeAmtBundle teamAmt(String userId, Map<String, TradeAmtBundle> teamAmtMemo) {
|
||||
TradeAmtBundle b = teamAmtMemo.get(userId);
|
||||
return b != null ? b : TradeAmtBundle.zeros();
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归下级(不含本人)在日期范围内四类金额汇总;parent_id 为父用户 user_id。
|
||||
*/
|
||||
private TradeAmtBundle teamAmtRecursive(
|
||||
String parentUserId,
|
||||
Map<String, List<String>> childrenByParentUserId,
|
||||
Map<String, TradeAmtBundle> ownAmtByUserId,
|
||||
Map<String, TradeAmtBundle> memo,
|
||||
Set<String> stack) {
|
||||
TradeAmtBundle cached = memo.get(parentUserId);
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
if (!stack.add(parentUserId)) {
|
||||
return TradeAmtBundle.zeros();
|
||||
}
|
||||
try {
|
||||
TradeAmtBundle sum = TradeAmtBundle.zeros();
|
||||
List<String> children = childrenByParentUserId.get(parentUserId);
|
||||
if (children != null) {
|
||||
for (String childUserId : children) {
|
||||
sum.addInPlace(ownAmt(childUserId, ownAmtByUserId));
|
||||
sum.addInPlace(teamAmtRecursive(childUserId, childrenByParentUserId, ownAmtByUserId, memo, stack));
|
||||
}
|
||||
}
|
||||
memo.put(parentUserId, sum);
|
||||
return sum;
|
||||
} finally {
|
||||
stack.remove(parentUserId);
|
||||
}
|
||||
}
|
||||
|
||||
/** 日期范围内按用户汇总的四类金额(与报表字段对应)。 */
|
||||
private static final class TradeAmtBundle {
|
||||
BigDecimal yestodayBuyAmt = BigDecimal.ZERO;
|
||||
BigDecimal dailySellAmt = BigDecimal.ZERO;
|
||||
BigDecimal dailyBuyAmt = BigDecimal.ZERO;
|
||||
BigDecimal diffAmt = BigDecimal.ZERO;
|
||||
|
||||
static TradeAmtBundle zeros() {
|
||||
return new TradeAmtBundle();
|
||||
}
|
||||
|
||||
void addFromReportRow(LbDailyUserTradeReport r) {
|
||||
yestodayBuyAmt = yestodayBuyAmt.add(defaultZero(r.getYestodayBuyAmt()));
|
||||
dailySellAmt = dailySellAmt.add(defaultZero(r.getDailySellAmt()));
|
||||
dailyBuyAmt = dailyBuyAmt.add(defaultZero(r.getDailyBuyAmt()));
|
||||
diffAmt = diffAmt.add(defaultZero(r.getDiffAmt()));
|
||||
}
|
||||
|
||||
void addInPlace(TradeAmtBundle o) {
|
||||
if (o == null) {
|
||||
return;
|
||||
}
|
||||
yestodayBuyAmt = yestodayBuyAmt.add(defaultZero(o.yestodayBuyAmt));
|
||||
dailySellAmt = dailySellAmt.add(defaultZero(o.dailySellAmt));
|
||||
dailyBuyAmt = dailyBuyAmt.add(defaultZero(o.dailyBuyAmt));
|
||||
diffAmt = diffAmt.add(defaultZero(o.diffAmt));
|
||||
}
|
||||
|
||||
TradeAmtBundle addCopy(TradeAmtBundle o) {
|
||||
TradeAmtBundle n = zeros();
|
||||
n.addInPlace(this);
|
||||
n.addInPlace(o != null ? o : zeros());
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user