修复部分bug
完善部分功能
This commit is contained in:
parent
0a4013b330
commit
f0418a8038
@ -17,6 +17,7 @@
|
|||||||
package com.zayac.admin.schedule;
|
package com.zayac.admin.schedule;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.zayac.admin.common.enums.DisEnableStatusEnum;
|
import com.zayac.admin.common.enums.DisEnableStatusEnum;
|
||||||
import com.zayac.admin.req.AgentDataVisualListReq;
|
import com.zayac.admin.req.AgentDataVisualListReq;
|
||||||
import com.zayac.admin.req.team.TeamInfoReq;
|
import com.zayac.admin.req.team.TeamInfoReq;
|
||||||
@ -32,6 +33,7 @@ import com.zayac.admin.system.model.entity.UserDO;
|
|||||||
import com.zayac.admin.system.model.req.AgentStatsReq;
|
import com.zayac.admin.system.model.req.AgentStatsReq;
|
||||||
import com.zayac.admin.system.model.resp.AccountResp;
|
import com.zayac.admin.system.model.resp.AccountResp;
|
||||||
import com.zayac.admin.system.service.*;
|
import com.zayac.admin.system.service.*;
|
||||||
|
import com.zayac.admin.utils.TableFormatter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -40,6 +42,7 @@ import java.text.NumberFormat;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@ -60,7 +63,8 @@ public class DailyReport {
|
|||||||
@Scheduled(cron = "0 40 11,14,17,21 * * ?")
|
@Scheduled(cron = "0 40 11,14,17,21 * * ?")
|
||||||
public void teamAccountDailyReport() {
|
public void teamAccountDailyReport() {
|
||||||
LocalDateTime nowDateTime = LocalDateTime.now();
|
LocalDateTime nowDateTime = LocalDateTime.now();
|
||||||
sendDailyReport(LocalDate.now(), nowDateTime, nowDateTime, false);
|
LocalDate nowDate = LocalDate.now();
|
||||||
|
sendDailyReport(nowDate, nowDate.atStartOfDay(), nowDateTime, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Scheduled(cron = "0 15 0 * * ?")
|
@Scheduled(cron = "0 15 0 * * ?")
|
||||||
@ -76,53 +80,56 @@ public class DailyReport {
|
|||||||
|
|
||||||
userIds.forEach(userId -> {
|
userIds.forEach(userId -> {
|
||||||
UserDO ministerUser = userService.getById(userId);
|
UserDO ministerUser = userService.getById(userId);
|
||||||
List<AccountResp> accounts = getTeamAccounts(ministerUser.getId());
|
|
||||||
List<UserDO> deptUsers = userService.getByDeptId(DisEnableStatusEnum.ENABLE, ministerUser.getDeptId());
|
List<UserDO> deptUsers = userService.getByDeptId(DisEnableStatusEnum.ENABLE, ministerUser.getDeptId());
|
||||||
|
if (ministerUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) {
|
||||||
accounts.forEach(accountResp -> {
|
List<String[]> rows = generateRows(ministerUser.getId(), startDateTime, endDateTime);
|
||||||
Team team = getLatestTeamInfo(accountResp, startDateTime, endDateTime);
|
String table = TableFormatter.formatTable(rows);
|
||||||
sendMinisterMessage(ministerUser, team.getList(), endDateTime);
|
telegramMessageService.sendMessage(ministerUser.getBotToken(), ministerUser.getCountGroupId(), table);
|
||||||
});
|
telegramMessageService
|
||||||
|
.sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, table);
|
||||||
|
}
|
||||||
|
|
||||||
AgentDataVisualListReq agentDataVisualListReq = AgentDataVisualListReq.builder().build();
|
AgentDataVisualListReq agentDataVisualListReq = AgentDataVisualListReq.builder().build();
|
||||||
|
//获取部长对应下级所有用户
|
||||||
deptUsers.forEach(deptUser -> {
|
deptUsers.forEach(deptUser -> {
|
||||||
String message = getDeptUserMessage(deptUser, agentDataVisualListReq, reportDate, saveStatics);
|
String message = getDeptUserMessage(deptUser, agentDataVisualListReq, reportDate, saveStatics);
|
||||||
if (deptUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) {
|
if (deptUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) {
|
||||||
telegramMessageService.sendMessage(deptUser.getBotToken(), deptUser.getCountGroupId(), message);
|
String botToken = StrUtil.isEmpty(deptUser.getBotToken()) ? ministerUser.getBotToken() : deptUser.getBotToken();
|
||||||
|
telegramMessageService.sendMessage(botToken, deptUser.getCountGroupId(), message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<AccountResp> getTeamAccounts(Long userId) {
|
|
||||||
return accountService.getAccountsByUserId(userId, DisEnableStatusEnum.ENABLE)
|
|
||||||
.stream()
|
|
||||||
.filter(AccountResp::getIsTeam)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Team getLatestTeamInfo(AccountResp accountResp, LocalDateTime startDateTime, LocalDateTime endDateTime) {
|
private Team getLatestTeamInfo(AccountResp accountResp, LocalDateTime startDateTime, LocalDateTime endDateTime) {
|
||||||
TeamInfoReq teamInfoReq = TeamInfoReq.builder().startDate(startDateTime).endDate(endDateTime).build();
|
TeamInfoReq teamInfoReq = TeamInfoReq.builder().startDate(startDateTime).endDate(endDateTime).build();
|
||||||
return teamService.getLatestTeamInfoAsync(accountResp, teamInfoReq).join();
|
return teamService.getLatestTeamInfoAsync(accountResp, teamInfoReq).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMinisterMessage(UserDO ministerUser, List<TeamAccount> list, LocalDateTime endDateTime) {
|
// private void buildMinisterMessage(String platformName, List<TeamAccount> list, StringBuilder notification, int[] totals) {
|
||||||
if (ministerUser.getNeedNotify() == DisEnableStatusEnum.ENABLE) {
|
// int totalNewMember = list.stream().mapToInt(TeamAccount::getSubMemberNum).sum();
|
||||||
int totalNewMember = list.stream().mapToInt(TeamAccount::getSubMemberNum).sum();
|
// int totalNewFirstDeposit = list.stream().mapToInt(TeamAccount::getFirstDepositNum).sum();
|
||||||
int totalNewFirstDeposit = list.stream().mapToInt(TeamAccount::getFirstDepositNum).sum();
|
// totals[0] += totalNewMember;
|
||||||
String percent = getPercent(totalNewFirstDeposit, totalNewMember);
|
// totals[1] += totalNewFirstDeposit;
|
||||||
String message = String
|
// String percent = getPercent(totalNewFirstDeposit, totalNewMember);
|
||||||
.format("截至%s 注册:*%d*,新增:*%d* 转化率: *%s*", endDateTime, totalNewMember, totalNewFirstDeposit, percent);
|
// List<String[]> rows = generateRows(ministerUser.getId(), startDateTime, endDateTime);
|
||||||
telegramMessageService.sendMessage(ministerUser.getBotToken(), ministerUser.getCountGroupId(), message);
|
// String table = TableFormatter.formatTable(rows);
|
||||||
}
|
// //notification.append(String.format("%-3s %-4d %-4d %-5s\n", platformName, totalNewMember, totalNewFirstDeposit, percent));
|
||||||
}
|
// notification.append(String.format("%-10s %-8d %-8d %-10s\n",
|
||||||
|
// padRight(platformName, 10), totalNewMember, totalNewFirstDeposit, percent));
|
||||||
|
// }
|
||||||
|
|
||||||
|
//获取需要发送给用户的信息
|
||||||
private String getDeptUserMessage(UserDO deptUser,
|
private String getDeptUserMessage(UserDO deptUser,
|
||||||
AgentDataVisualListReq agentDataVisualListReq,
|
AgentDataVisualListReq agentDataVisualListReq,
|
||||||
LocalDate reportDate,
|
LocalDate reportDate,
|
||||||
boolean saveStatics) {
|
boolean saveStatics) {
|
||||||
StringBuilder message = new StringBuilder();
|
StringBuilder message = new StringBuilder();
|
||||||
List<AccountResp> currUserAccounts = getTeamAccounts(deptUser.getId());
|
// 主线注册新增不用报数,过滤
|
||||||
|
List<AccountResp> currUserAccounts = accountService.getAccountsByUserId(deptUser.getId(), DisEnableStatusEnum.ENABLE)
|
||||||
|
.stream()
|
||||||
|
.filter(accountResp -> !accountResp.getIsTeam())
|
||||||
|
.toList();
|
||||||
|
|
||||||
currUserAccounts.forEach(currAccount -> {
|
currUserAccounts.forEach(currAccount -> {
|
||||||
CompletableFuture<AgentDataVisualList> future = agentDataVisualListService
|
CompletableFuture<AgentDataVisualList> future = agentDataVisualListService
|
||||||
@ -161,4 +168,34 @@ public class DailyReport {
|
|||||||
percentInstance.setMinimumFractionDigits(2);
|
percentInstance.setMinimumFractionDigits(2);
|
||||||
return percentInstance.format(d1 / d2);
|
return percentInstance.format(d1 / d2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String padRight(String s, int n) {
|
||||||
|
int length = s.length() + (int) s.chars().filter(ch -> ch > 0xFF).count();
|
||||||
|
return String.format("%-" + (n - length + s.length()) + "s", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String[]> generateRows(Long userId, LocalDateTime startDateTime, LocalDateTime endDateTime) {
|
||||||
|
List<String[]> rows = new ArrayList<>();
|
||||||
|
rows.add(new String[]{"平台", "注册", "新增", "转化率"});
|
||||||
|
rows.add(new String[]{"----", "----", "----", "----"});
|
||||||
|
|
||||||
|
List<AccountResp> accounts = accountService.getAccountsByUserId(userId, DisEnableStatusEnum.ENABLE)
|
||||||
|
.stream()
|
||||||
|
.filter(AccountResp::getIsTeam)
|
||||||
|
.toList();
|
||||||
|
int[] totals = {0, 0};
|
||||||
|
|
||||||
|
accounts.forEach(accountResp -> {
|
||||||
|
Team team = getLatestTeamInfo(accountResp, startDateTime, endDateTime);
|
||||||
|
int totalNewMember = team.getList().stream().mapToInt(TeamAccount::getSubMemberNum).sum();
|
||||||
|
int totalNewFirstDeposit = team.getList().stream().mapToInt(TeamAccount::getFirstDepositNum).sum();
|
||||||
|
totals[0] += totalNewMember;
|
||||||
|
totals[1] += totalNewFirstDeposit;
|
||||||
|
String percent = getPercent(totalNewFirstDeposit, totalNewMember);
|
||||||
|
rows.add(new String[]{accountResp.getPlatformName(), String.valueOf(totalNewMember), String.valueOf(totalNewFirstDeposit), percent});
|
||||||
|
});
|
||||||
|
|
||||||
|
rows.add(new String[]{"总注册", String.valueOf(totals[0]), String.valueOf(totals[1]), getPercent(totals[1], totals[0])});
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,20 +70,21 @@ public class TelegramTeamMessageSchedule {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> processUser(UserDO user, LocalDate nowDate, LocalDateTime nowDateTime) {
|
private CompletableFuture<Void> processUser(UserDO minister, LocalDate nowDate, LocalDateTime nowDateTime) {
|
||||||
List<AccountResp> accounts = accountService.getAccountsByUserId(user.getId(), DisEnableStatusEnum.ENABLE)
|
List<AccountResp> accounts = accountService.getAccountsByUserId(minister.getId(), DisEnableStatusEnum.ENABLE)
|
||||||
.stream()
|
.stream()
|
||||||
.filter(AccountResp::getIsTeam)
|
.filter(AccountResp::getIsTeam)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
List<CompletableFuture<Void>> futures = accounts.stream()
|
List<CompletableFuture<Void>> futures = accounts.stream()
|
||||||
.map(account -> processTeamAccount(account, nowDate, nowDateTime))
|
.map(account -> processTeamAccount(minister, account, nowDate, nowDateTime))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> processTeamAccount(AccountResp account,
|
private CompletableFuture<Void> processTeamAccount(UserDO minister,
|
||||||
|
AccountResp account,
|
||||||
LocalDate nowDate,
|
LocalDate nowDate,
|
||||||
LocalDateTime nowDateTime) {
|
LocalDateTime nowDateTime) {
|
||||||
TeamInfoReq teamInfoReq = TeamInfoReq.builder()
|
TeamInfoReq teamInfoReq = TeamInfoReq.builder()
|
||||||
@ -102,9 +103,9 @@ public class TelegramTeamMessageSchedule {
|
|||||||
.collect(Collectors.toMap(TeamAccount::getAgentName, Function.identity()));
|
.collect(Collectors.toMap(TeamAccount::getAgentName, Function.identity()));
|
||||||
|
|
||||||
CompletableFuture<Void> registrationProcess = registrationService
|
CompletableFuture<Void> registrationProcess = registrationService
|
||||||
.processRegistration(account, currentTeamInfo, prevTeamInfo, nowDate, teamAccountMap);
|
.processRegistration(minister, account, currentTeamInfo, prevTeamInfo, nowDate, teamAccountMap);
|
||||||
CompletableFuture<Void> depositProcess = depositService
|
CompletableFuture<Void> depositProcess = depositService
|
||||||
.processDeposits(account, currentTeamInfo, prevTeamInfo, nowDate, nowDateTime);
|
.processDeposits(minister, account, currentTeamInfo, prevTeamInfo, nowDate, nowDateTime);
|
||||||
|
|
||||||
return CompletableFuture.allOf(registrationProcess, depositProcess)
|
return CompletableFuture.allOf(registrationProcess, depositProcess)
|
||||||
.thenRun(() -> teamService.updateTeamInfo(account, currentTeamInfo));
|
.thenRun(() -> teamService.updateTeamInfo(account, currentTeamInfo));
|
||||||
|
@ -18,6 +18,7 @@ package com.zayac.admin.service;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.zayac.admin.common.enums.DisEnableStatusEnum;
|
||||||
import com.zayac.admin.constant.ApiPathConstants;
|
import com.zayac.admin.constant.ApiPathConstants;
|
||||||
import com.zayac.admin.req.MemberDetailsReq;
|
import com.zayac.admin.req.MemberDetailsReq;
|
||||||
import com.zayac.admin.req.PayRecordsListReq;
|
import com.zayac.admin.req.PayRecordsListReq;
|
||||||
@ -56,7 +57,8 @@ public class DepositService {
|
|||||||
private final TelegramMessageService telegramMessageService;
|
private final TelegramMessageService telegramMessageService;
|
||||||
private final AccountService accountService;
|
private final AccountService accountService;
|
||||||
|
|
||||||
public CompletableFuture<Void> processDeposits(AccountResp account,
|
public CompletableFuture<Void> processDeposits(UserDO minister,
|
||||||
|
AccountResp account,
|
||||||
Team currentTeam,
|
Team currentTeam,
|
||||||
Team previousTeam,
|
Team previousTeam,
|
||||||
LocalDate nowDate,
|
LocalDate nowDate,
|
||||||
@ -64,69 +66,73 @@ public class DepositService {
|
|||||||
return CompletableFuture.runAsync(() -> {
|
return CompletableFuture.runAsync(() -> {
|
||||||
if (previousTeam != null && currentTeam.getFirstDepositNum() > previousTeam.getFirstDepositNum()) {
|
if (previousTeam != null && currentTeam.getFirstDepositNum() > previousTeam.getFirstDepositNum()) {
|
||||||
PayRecordsListReq req = PayRecordsListReq.builder()
|
PayRecordsListReq req = PayRecordsListReq.builder()
|
||||||
.startDate(nowDate)
|
.startDate(nowDate)
|
||||||
.endDate(nowDate)
|
.endDate(nowDate)
|
||||||
.pageSize(100)
|
.pageSize(100)
|
||||||
.payState(2)
|
.payState(2)
|
||||||
.build();
|
.build();
|
||||||
CompletableFuture<Pagination<List<PayRecord>>> paginationCompletableFuture = completableFutureWebClientService
|
CompletableFuture<Pagination<List<PayRecord>>> paginationCompletableFuture = completableFutureWebClientService
|
||||||
.fetchDataForAccount(account, ApiPathConstants.PAY_RECORDS_LIST_URL, req, new ParameterizedTypeReference<>() {
|
.fetchDataForAccount(account, ApiPathConstants.PAY_RECORDS_LIST_URL, req, new ParameterizedTypeReference<>() {
|
||||||
});
|
});
|
||||||
List<TeamAccountWithChange> changedTeamAccounts = findChangedTeamAccount(previousTeam, currentTeam);
|
List<TeamAccountWithChange> changedTeamAccounts = findChangedTeamAccount(previousTeam, currentTeam);
|
||||||
Set<String> changedAgentNames = changedTeamAccounts.stream()
|
Set<String> changedAgentNames = changedTeamAccounts.stream()
|
||||||
.filter(teamAccountWithChange -> teamAccountWithChange.getNewDepositNum() > 0)
|
.filter(teamAccountWithChange -> teamAccountWithChange.getNewDepositNum() > 0)
|
||||||
.map(TeamAccountWithChange::getAgentName)
|
.map(TeamAccountWithChange::getAgentName)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
paginationCompletableFuture.thenApply(Pagination::getList).thenAccept(payRecords -> {
|
paginationCompletableFuture.thenApply(Pagination::getList).thenAccept(payRecords -> {
|
||||||
Map<String, List<String>> agentNameWithNames = payRecords.stream()
|
Map<String, List<String>> agentNameWithNames = payRecords.stream()
|
||||||
.filter(record -> record.getCreatedAt().isAfter(nowDateTime.minusHours(1)) && changedAgentNames
|
.filter(record -> record.getCreatedAt().isAfter(nowDateTime.minusHours(1)) && changedAgentNames
|
||||||
.contains(record.getAgentName()))
|
.contains(record.getAgentName()))
|
||||||
.collect(Collectors.groupingBy(PayRecord::getAgentName, Collectors
|
.collect(Collectors.groupingBy(PayRecord::getAgentName, Collectors
|
||||||
.mapping(PayRecord::getName, Collectors.collectingAndThen(Collectors
|
.mapping(PayRecord::getName, Collectors.collectingAndThen(Collectors
|
||||||
.toSet(), ArrayList::new))));
|
.toSet(), ArrayList::new))));
|
||||||
|
|
||||||
agentNameWithNames.forEach((agentName, names) -> {
|
agentNameWithNames.forEach((agentName, names) -> {
|
||||||
StringBuilder depositResults = new StringBuilder();
|
StringBuilder depositResults = new StringBuilder();
|
||||||
AtomicInteger depositCounter = new AtomicInteger(0);
|
AtomicInteger depositCounter = new AtomicInteger(0);
|
||||||
|
|
||||||
TeamAccountWithChange targetTeamAccount = changedTeamAccounts.stream()
|
TeamAccountWithChange targetTeamAccount = changedTeamAccounts.stream()
|
||||||
.filter(teamAccount -> StrUtil.equals(teamAccount.getAgentName(), agentName))
|
.filter(teamAccount -> StrUtil.equals(teamAccount.getAgentName(), agentName))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow(() -> new BusinessException(String
|
.orElseThrow(() -> new BusinessException(String
|
||||||
.format("can not find agent name %s", agentName)));
|
.format("can not find agent name %s", agentName)));
|
||||||
|
|
||||||
List<CompletableFuture<Void>> fetchFutures = names.stream()
|
List<CompletableFuture<Void>> fetchFutures = names.stream()
|
||||||
.map(name -> fetchMemberDetails(account, name, nowDate).thenAccept(member -> {
|
.map(name -> fetchMemberDetails(account, name, nowDate).thenAccept(member -> {
|
||||||
payRecords.stream()
|
payRecords.stream()
|
||||||
.filter(record -> record.getCreatedAt().equals(member.getFirstPayAt()))
|
.filter(record -> record.getCreatedAt().equals(member.getFirstPayAt()))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.ifPresent(record -> {
|
.ifPresent(record -> {
|
||||||
if (depositCounter.getAndIncrement() < targetTeamAccount.getNewDepositNum()) {
|
if (depositCounter.getAndIncrement() < targetTeamAccount.getNewDepositNum()) {
|
||||||
depositResults.append(telegramMessageService
|
depositResults.append(telegramMessageService
|
||||||
.buildDepositResultsMessage(member.getName(), record.getScoreAmount()));
|
.buildDepositResultsMessage(member.getName(), record.getScoreAmount()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).exceptionally(ex -> {
|
}).exceptionally(ex -> {
|
||||||
log.error("Error fetching details for member {}: {}", name, ex.getMessage());
|
log.error("Error fetching details for member {}: {}", name, ex.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}))
|
}))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
CompletableFuture<Void> allFetches = CompletableFuture.allOf(fetchFutures
|
CompletableFuture<Void> allFetches = CompletableFuture.allOf(fetchFutures
|
||||||
.toArray(new CompletableFuture[0]));
|
.toArray(new CompletableFuture[0]));
|
||||||
|
|
||||||
allFetches.thenRun(() -> {
|
allFetches.thenRun(() -> {
|
||||||
if (!depositResults.isEmpty()) {
|
if (!depositResults.isEmpty()) {
|
||||||
String notification = telegramMessageService
|
String notification = telegramMessageService
|
||||||
.buildDepositMessage(agentName, targetTeamAccount.getNewDepositNum(), depositResults
|
.buildDepositMessage(agentName, targetTeamAccount.getNewDepositNum(), depositResults
|
||||||
.toString(), targetTeamAccount.getFirstDepositNum());
|
.toString(), targetTeamAccount.getFirstDepositNum());
|
||||||
UserDO currUser = accountService.getUserByAccountUsername(agentName);
|
UserDO currUser = accountService.getUserByAccountUsername(agentName);
|
||||||
|
if (currUser != null && DisEnableStatusEnum.ENABLE.equals(currUser.getNeedNotify())) {
|
||||||
|
String botToken = StrUtil.isEmpty(currUser.getBotToken()) ? minister.getBotToken() : currUser.getBotToken();
|
||||||
|
telegramMessageService.sendMessage(botToken, currUser.getGroupId(), notification);
|
||||||
|
}
|
||||||
telegramMessageService
|
telegramMessageService
|
||||||
.sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification);
|
.sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification);
|
||||||
}
|
}
|
||||||
}).exceptionally(ex -> {
|
}).exceptionally(ex -> {
|
||||||
log.error("Error sending notification for account {}: {}", account.getId(), ex
|
log.error("Error sending notification for account {}: {}", account.getId(), ex
|
||||||
.getMessage());
|
.getMessage());
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -140,54 +146,54 @@ public class DepositService {
|
|||||||
|
|
||||||
private CompletableFuture<Member> fetchMemberDetails(AccountResp account, String name, LocalDate nowDate) {
|
private CompletableFuture<Member> fetchMemberDetails(AccountResp account, String name, LocalDate nowDate) {
|
||||||
TeamMemberListReq memberListReq = TeamMemberListReq.builder()
|
TeamMemberListReq memberListReq = TeamMemberListReq.builder()
|
||||||
.name(name)
|
.name(name)
|
||||||
.startDate(nowDate)
|
.startDate(nowDate)
|
||||||
.endDate(nowDate)
|
.endDate(nowDate)
|
||||||
.status(1)
|
.status(1)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
CompletableFuture<MemberPagination<List<Member>>> memberFuture = completableFutureWebClientService
|
CompletableFuture<MemberPagination<List<Member>>> memberFuture = completableFutureWebClientService
|
||||||
.fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() {
|
.fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() {
|
||||||
});
|
});
|
||||||
|
|
||||||
return memberFuture.thenApply(MemberPagination::getList)
|
return memberFuture.thenApply(MemberPagination::getList)
|
||||||
.thenApply(list -> list.stream().findFirst())
|
.thenApply(list -> list.stream().findFirst())
|
||||||
.thenCompose(optionalMember -> optionalMember.map(member -> fetchDetailedMemberInfo(account, member
|
.thenCompose(optionalMember -> optionalMember.map(member -> fetchDetailedMemberInfo(account, member
|
||||||
.getId(), nowDate)).orElseThrow(() -> new RuntimeException("没有找到匹配的成员信息")));
|
.getId(), nowDate)).orElseThrow(() -> new RuntimeException("没有找到匹配的成员信息")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Member> fetchDetailedMemberInfo(AccountResp account, Long memberId, LocalDate nowDate) {
|
private CompletableFuture<Member> fetchDetailedMemberInfo(AccountResp account, Long memberId, LocalDate nowDate) {
|
||||||
MemberDetailsReq detailsReq = MemberDetailsReq.builder()
|
MemberDetailsReq detailsReq = MemberDetailsReq.builder()
|
||||||
.id(memberId)
|
.id(memberId)
|
||||||
.startDate(nowDate)
|
.startDate(nowDate)
|
||||||
.endDate(nowDate)
|
.endDate(nowDate)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
return completableFutureWebClientService
|
return completableFutureWebClientService
|
||||||
.fetchDataForAccount(account, ApiPathConstants.MEMBER_DETAIL_URL, detailsReq, new ParameterizedTypeReference<>() {
|
.fetchDataForAccount(account, ApiPathConstants.MEMBER_DETAIL_URL, detailsReq, new ParameterizedTypeReference<>() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TeamAccountWithChange> findChangedTeamAccount(Team prevTeam, Team currTeam) {
|
private List<TeamAccountWithChange> findChangedTeamAccount(Team prevTeam, Team currTeam) {
|
||||||
Map<Long, TeamAccount> team2AccountMap = currTeam.getList()
|
Map<Long, TeamAccount> team2AccountMap = currTeam.getList()
|
||||||
.stream()
|
.stream()
|
||||||
.collect(Collectors.toMap(TeamAccount::getId, account -> account));
|
.collect(Collectors.toMap(TeamAccount::getId, account -> account));
|
||||||
|
|
||||||
return prevTeam.getList()
|
return prevTeam.getList()
|
||||||
.stream()
|
.stream()
|
||||||
.filter(account1 -> team2AccountMap.containsKey(account1.getId()))
|
.filter(account1 -> team2AccountMap.containsKey(account1.getId()))
|
||||||
.map(account1 -> {
|
.map(account1 -> {
|
||||||
TeamAccount account2 = team2AccountMap.get(account1.getId());
|
TeamAccount account2 = team2AccountMap.get(account1.getId());
|
||||||
TeamAccountWithChange changedAccount = new TeamAccountWithChange();
|
TeamAccountWithChange changedAccount = new TeamAccountWithChange();
|
||||||
BeanUtil.copyProperties(account2, changedAccount);
|
BeanUtil.copyProperties(account2, changedAccount);
|
||||||
if (account1.getFirstDepositNum() != account2.getFirstDepositNum()) {
|
if (account1.getFirstDepositNum() != account2.getFirstDepositNum()) {
|
||||||
changedAccount.setNewDepositNum(account2.getFirstDepositNum() - account1.getFirstDepositNum());
|
changedAccount.setNewDepositNum(account2.getFirstDepositNum() - account1.getFirstDepositNum());
|
||||||
}
|
}
|
||||||
if (account1.getSubMemberNum() != account2.getSubMemberNum()) {
|
if (account1.getSubMemberNum() != account2.getSubMemberNum()) {
|
||||||
changedAccount.setNewRegisterNum(account2.getSubMemberNum() - account1.getSubMemberNum());
|
changedAccount.setNewRegisterNum(account2.getSubMemberNum() - account1.getSubMemberNum());
|
||||||
}
|
}
|
||||||
return changedAccount;
|
return changedAccount;
|
||||||
})
|
})
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.zayac.admin.service;
|
package com.zayac.admin.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.zayac.admin.common.enums.DisEnableStatusEnum;
|
||||||
import com.zayac.admin.constant.ApiPathConstants;
|
import com.zayac.admin.constant.ApiPathConstants;
|
||||||
import com.zayac.admin.req.team.TeamMemberReq;
|
import com.zayac.admin.req.team.TeamMemberReq;
|
||||||
import com.zayac.admin.resp.MemberPagination;
|
import com.zayac.admin.resp.MemberPagination;
|
||||||
@ -41,11 +43,11 @@ import java.util.stream.Collectors;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class RegistrationService {
|
public class RegistrationService {
|
||||||
private final CompletableFutureWebClientService completableFutureWebClientService;
|
private final CompletableFutureWebClientService completableFutureWebClientService;
|
||||||
private final TelegramMessageService notificationService;
|
|
||||||
private final TelegramMessageService telegramMessageService;
|
private final TelegramMessageService telegramMessageService;
|
||||||
private final AccountService accountService;
|
private final AccountService accountService;
|
||||||
|
|
||||||
public CompletableFuture<Void> processRegistration(AccountResp account,
|
public CompletableFuture<Void> processRegistration(UserDO minister,
|
||||||
|
AccountResp account,
|
||||||
Team currentTeamInfo,
|
Team currentTeamInfo,
|
||||||
Team prevTeamInfo,
|
Team prevTeamInfo,
|
||||||
LocalDate nowDate,
|
LocalDate nowDate,
|
||||||
@ -53,30 +55,31 @@ public class RegistrationService {
|
|||||||
if (prevTeamInfo != null && currentTeamInfo.getSubMemberCount() > prevTeamInfo.getSubMemberCount()) {
|
if (prevTeamInfo != null && currentTeamInfo.getSubMemberCount() > prevTeamInfo.getSubMemberCount()) {
|
||||||
int registerCount = currentTeamInfo.getSubMemberCount() - prevTeamInfo.getSubMemberCount();
|
int registerCount = currentTeamInfo.getSubMemberCount() - prevTeamInfo.getSubMemberCount();
|
||||||
TeamMemberReq memberListReq = TeamMemberReq.builder()
|
TeamMemberReq memberListReq = TeamMemberReq.builder()
|
||||||
.registerStartDate(nowDate)
|
.registerStartDate(nowDate)
|
||||||
.registerEndDate(nowDate)
|
.registerEndDate(nowDate)
|
||||||
.startDate(nowDate)
|
.startDate(nowDate)
|
||||||
.endDate(nowDate)
|
.endDate(nowDate)
|
||||||
.registerSort(1)
|
.registerSort(1)
|
||||||
.pageSize(registerCount)
|
.pageSize(registerCount)
|
||||||
.build();
|
.build();
|
||||||
CompletableFuture<MemberPagination<List<TeamMember>>> memberPaginationCompletableFuture = completableFutureWebClientService
|
CompletableFuture<MemberPagination<List<TeamMember>>> memberPaginationCompletableFuture = completableFutureWebClientService
|
||||||
.fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() {
|
.fetchDataForAccount(account, ApiPathConstants.MEMBER_TEAM_LIST_URL, memberListReq, new ParameterizedTypeReference<>() {
|
||||||
});
|
});
|
||||||
return memberPaginationCompletableFuture.thenApply(MemberPagination::getList).thenAccept(members -> {
|
return memberPaginationCompletableFuture.thenApply(MemberPagination::getList).thenAccept(members -> {
|
||||||
log.info("Successfully get {} new registered members", members.size());
|
log.info("Successfully get {} new registered members", members.size());
|
||||||
if (!members.isEmpty()) {
|
if (!members.isEmpty()) {
|
||||||
Map<String, List<TeamMember>> groupByTopAgentName = members.stream()
|
Map<String, List<TeamMember>> groupByTopAgentName = members.stream()
|
||||||
.collect(Collectors.groupingBy(TeamMember::getTopAgentName));
|
.collect(Collectors.groupingBy(TeamMember::getTopAgentName));
|
||||||
groupByTopAgentName.forEach((accountName, accountMembers) -> {
|
groupByTopAgentName.forEach((accountName, accountMembers) -> {
|
||||||
String notification = telegramMessageService
|
String notification = telegramMessageService
|
||||||
.buildRegistrationMessage(accountName, accountMembers, teamAccountMap.get(accountName));
|
.buildRegistrationMessage(accountName, accountMembers, teamAccountMap.get(accountName));
|
||||||
UserDO currUser = accountService.getUserByAccountUsername(accountName);
|
UserDO currUser = accountService.getUserByAccountUsername(accountName);
|
||||||
// if (currUser != null && DisEnableStatusEnum.ENABLE.equals(currUser.getNeedNotify())) {
|
if (currUser != null && DisEnableStatusEnum.ENABLE.equals(currUser.getNeedNotify())) {
|
||||||
// telegramMessageService.sendMessage(currUser.getBotToken(), currUser.getGroupId(), notification);
|
String botToken = StrUtil.isEmpty(currUser.getBotToken()) ? minister.getBotToken() : currUser.getBotToken();
|
||||||
// }
|
telegramMessageService.sendMessage(botToken, currUser.getGroupId(), notification);
|
||||||
|
}
|
||||||
telegramMessageService
|
telegramMessageService
|
||||||
.sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification);
|
.sendMessage("6013830443:AAHUOS4v6Ln19ziZkH-L28-HZQLJrGcvhto", 6054562838L, notification);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -33,26 +33,37 @@ public class TelegramMessageService {
|
|||||||
private final RabbitTemplate rabbitTemplate;
|
private final RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
public void sendMessage(String botToken, Long targetId, String message) {
|
public void sendMessage(String botToken, Long targetId, String message) {
|
||||||
String fullMessage = String.format("%s|%s|%s", botToken, targetId, escapeMarkdown(message));
|
if (!containsHTMLCharacters(message)) {
|
||||||
|
message = escapeMarkdown(message);
|
||||||
|
}
|
||||||
|
String fullMessage = String.format("%s|%s|%s", botToken, targetId, message);
|
||||||
this.rabbitTemplate.convertAndSend("message_queue", fullMessage);
|
this.rabbitTemplate.convertAndSend("message_queue", fullMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String escapeMarkdown(String text) {
|
private static String escapeMarkdown(String text) {
|
||||||
|
|
||||||
List<Character> escapeChars = Arrays
|
List<Character> escapeChars = Arrays
|
||||||
.asList('_', '[', ']', '(', ')', '~', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!');
|
.asList('_', '[', ']', '(', ')', '~', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!');
|
||||||
for (Character charItem : escapeChars) {
|
for (Character charItem : escapeChars) {
|
||||||
text = text.replace(charItem.toString(), "\\" + charItem);
|
text = text.replace(charItem.toString(), "\\" + charItem);
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean containsHTMLCharacters(String text) {
|
||||||
|
List<String> htmlTags = Arrays.asList("<b>", "<i>", "<a>", "<code>", "<pre>");
|
||||||
|
if (htmlTags.stream().anyMatch(text::contains)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public String buildRegistrationMessage(String accountName,
|
public String buildRegistrationMessage(String accountName,
|
||||||
List<TeamMember> accountMembers,
|
List<TeamMember> accountMembers,
|
||||||
TeamAccount teamAccount) {
|
TeamAccount teamAccount) {
|
||||||
String memberNames = accountMembers.stream().map(TeamMember::getName).collect(Collectors.joining(", "));
|
String memberNames = accountMembers.stream().map(TeamMember::getName).collect(Collectors.joining(", "));
|
||||||
return String.format("👏 %s 注册: %d 用户: `%s` 总数:*%d*", accountName, accountMembers
|
return String.format("👏 %s 注册: %d 用户: `%s` 总数:*%d*", accountName, accountMembers
|
||||||
.size(), memberNames, teamAccount.getSubMemberNum());
|
.size(), memberNames, teamAccount.getSubMemberNum());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String buildDepositMessage(String agentName, int newDepositNum, String depositResults, int firstDepositNum) {
|
public String buildDepositMessage(String agentName, int newDepositNum, String depositResults, int firstDepositNum) {
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.zayac.admin.utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TableFormatter {
|
||||||
|
|
||||||
|
public static String formatMarkdownTable(List<String[]> rows) {
|
||||||
|
int[] colWidths = calculateColumnWidths(rows);
|
||||||
|
StringBuilder table = new StringBuilder("```\n");
|
||||||
|
for (String[] row : rows) {
|
||||||
|
table.append(formatRow(row, colWidths)).append("\n");
|
||||||
|
}
|
||||||
|
table.append("```");
|
||||||
|
return table.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatTable(List<String[]> rows) {
|
||||||
|
int[] colWidths = calculateColumnWidths(rows);
|
||||||
|
StringBuilder table = new StringBuilder();
|
||||||
|
for (String[] row : rows) {
|
||||||
|
table.append(formatRow(row, colWidths)).append("\n");
|
||||||
|
}
|
||||||
|
return table.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatTableAsHtml(List<String[]> rows) {
|
||||||
|
int[] colWidths = calculateColumnWidths(rows);
|
||||||
|
StringBuilder table = new StringBuilder("<pre>\n");
|
||||||
|
for (String[] row : rows) {
|
||||||
|
table.append(formatRow(row, colWidths)).append("\n");
|
||||||
|
}
|
||||||
|
table.append("</pre>");
|
||||||
|
return table.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] calculateColumnWidths(List<String[]> rows) {
|
||||||
|
int[] colWidths = new int[rows.get(0).length];
|
||||||
|
for (String[] row : rows) {
|
||||||
|
for (int i = 0; i < row.length; i++) {
|
||||||
|
colWidths[i] = Math.max(colWidths[i], getStringWidth(row[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return colWidths;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatRow(String[] row, int[] colWidths) {
|
||||||
|
StringBuilder formattedRow = new StringBuilder();
|
||||||
|
for (int i = 0; i < row.length; i++) {
|
||||||
|
formattedRow.append(padRight(row[i], colWidths[i])).append(" ");
|
||||||
|
}
|
||||||
|
return formattedRow.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getStringWidth(String s) {
|
||||||
|
return s.codePoints().map(ch -> ch > 0xFF ? 2 : 1).sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String padRight(String s, int n) {
|
||||||
|
int width = getStringWidth(s);
|
||||||
|
int padding = n - width;
|
||||||
|
return s + " ".repeat(Math.max(0, padding));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user