- SysOriginPlatformEnum 新增 BZIZI("Bzizi", 12) 枚举值
- GameSysOriginEnum 新增 BZIZI("Bzizi")
- FreightGoldToUsdRatioEnum 新增 BZIZI(10000)
- 将主业务代码及测试代码中所有写死的 LIKEI 替换为 BZIZI(共 65 个文件)
- 保留枚举定义中的 LIKEI 值及日志消息不变
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
308 lines
13 KiB
Java
308 lines
13 KiB
Java
import com.red.circle.OtherServiceApplication;
|
||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||
import com.red.circle.other.domain.model.user.UserProfile;
|
||
import com.red.circle.other.infra.common.team.decay.ListMemberWorkDecay;
|
||
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
|
||
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService;
|
||
import com.red.circle.other.inner.model.cmd.team.TeamMemberWorkQryCmd;
|
||
import com.red.circle.other.inner.model.dto.agency.agency.TeamMemberWorkDTO;
|
||
import com.red.circle.other.inner.model.dto.agency.agency.TeamMemberWorkDailyTargetDTO;
|
||
import com.red.circle.tool.core.date.TimestampUtils;
|
||
import org.junit.Test;
|
||
import org.junit.runner.RunWith;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.boot.test.context.SpringBootTest;
|
||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||
import org.springframework.data.mongodb.core.query.Criteria;
|
||
import org.springframework.data.mongodb.core.query.Query;
|
||
import org.springframework.data.mongodb.core.query.Update;
|
||
import org.springframework.test.context.junit4.SpringRunner;
|
||
|
||
import java.util.*;
|
||
import java.util.stream.Collectors;
|
||
|
||
@SpringBootTest(classes = OtherServiceApplication.class)
|
||
@RunWith(SpringRunner.class)
|
||
public class AnchorTargetTest {
|
||
|
||
@Autowired
|
||
private TeamMemberTargetService teamMemberTargetService;
|
||
@Autowired
|
||
private ListMemberWorkDecay listMemberWorkDecay;
|
||
@Autowired
|
||
private MongoTemplate mongoTemplate;
|
||
@Autowired
|
||
private UserProfileGateway userProfileGateway;
|
||
|
||
|
||
/**
|
||
* 扣除主播目标
|
||
*/
|
||
@Test
|
||
public void AnchorTargetTest(){
|
||
Long userId = 1987522531364773890L;
|
||
Long deductValue = 300000L; // 要扣除的目标值
|
||
|
||
TeamMemberWorkQryCmd cmd = new TeamMemberWorkQryCmd();
|
||
cmd.setMemberUserId(userId);
|
||
cmd.setSysOrigin("BZIZI");
|
||
List<TeamMemberWorkDTO> execute = listMemberWorkDecay.execute(cmd);
|
||
|
||
// 1. 筛选 billStatus = UNPAID 的数据
|
||
List<TeamMemberWorkDTO> unpaidList = execute.stream()
|
||
.filter(work -> "UNPAID".equals(work.getBillStatus()))
|
||
.limit(1)
|
||
.toList();
|
||
|
||
System.out.println("未结算的工单数量: " + unpaidList.size());
|
||
|
||
for (TeamMemberWorkDTO work : unpaidList) {
|
||
// 2. 统计 dailyTargets 的 acceptGiftValue 的和
|
||
Long totalAcceptGiftValue = work.getTarget().getDailyTargets().stream()
|
||
.mapToLong(TeamMemberWorkDailyTargetDTO::getAcceptGiftValue)
|
||
.sum();
|
||
|
||
System.out.println("工单ID: " + work.getId() + ", 总收礼物价值: " + totalAcceptGiftValue);
|
||
|
||
// 3. 检查目标值够不够扣
|
||
if (totalAcceptGiftValue < deductValue) {
|
||
System.out.println("目标值不足,无法扣除。需要: " + deductValue + ", 当前: " + totalAcceptGiftValue);
|
||
continue;
|
||
}
|
||
|
||
// 4. 从第一天开始扣除
|
||
Long remainingDeduct = deductValue;
|
||
List<TeamMemberWorkDailyTargetDTO> dailyTargets = work.getTarget().getDailyTargets();
|
||
boolean hasModified = false; // 标记是否有修改
|
||
|
||
for (int i = 0; i < dailyTargets.size(); i++) {
|
||
TeamMemberWorkDailyTargetDTO dailyTarget = dailyTargets.get(i);
|
||
Long currentValue = dailyTarget.getAcceptGiftValue();
|
||
|
||
if (remainingDeduct <= 0) {
|
||
break;
|
||
}
|
||
|
||
if (currentValue > 0) { // 只有当前值大于0时才可能修改
|
||
hasModified = true; // 标记为已修改
|
||
|
||
if (currentValue >= remainingDeduct) {
|
||
// 当前天的值足够扣除剩余部分
|
||
dailyTarget.setAcceptGiftValue(currentValue - remainingDeduct);
|
||
System.out.println("日期 " + dailyTarget.getDateNumber() + " 扣除: " + remainingDeduct + ", 剩余: " + (currentValue - remainingDeduct));
|
||
remainingDeduct = 0L;
|
||
} else {
|
||
// 当前天的值不够,全部扣除
|
||
dailyTarget.setAcceptGiftValue(0L);
|
||
remainingDeduct -= currentValue;
|
||
System.out.println("日期 " + dailyTarget.getDateNumber() + " 扣除: " + currentValue + ", 剩余需扣除: " + remainingDeduct);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 5. 只有当有修改时才更新 MongoDB
|
||
if (hasModified) {
|
||
updateTeamMemberTarget(work.getId(), dailyTargets);
|
||
System.out.println("工单 " + work.getId() + " 扣除完成,已更新到MongoDB");
|
||
} else {
|
||
System.out.println("工单 " + work.getId() + " 无需修改,跳过更新");
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 批量扣除主播目标
|
||
*/
|
||
@Test
|
||
public void batchAnchorTargetDeduct() {
|
||
Map<Long, Long> map = Map.ofEntries(
|
||
Map.entry(22222L, 3750000L),
|
||
Map.entry(8846195L, 1125000L),
|
||
Map.entry(8846188L, 150000L),
|
||
Map.entry(8846174L, 750000L),
|
||
Map.entry(8846185L, 750000L),
|
||
Map.entry(8848862L, 6000000L),
|
||
Map.entry(8849422L, 300000L),
|
||
Map.entry(8846353L, 300000L)
|
||
);
|
||
|
||
// 将account转换为userId并构建batchDeductMap
|
||
Map<Long, Long> batchDeductMap = new HashMap<>();
|
||
map.forEach((account, amount) -> {
|
||
UserProfile userProfile = userProfileGateway.getByAccount("BZIZI", String.valueOf(account));
|
||
if (Objects.nonNull(userProfile)) {
|
||
batchDeductMap.put(userProfile.getId(), amount);
|
||
} else {
|
||
throw new RuntimeException("账号不存在:" + account);
|
||
}
|
||
});
|
||
|
||
|
||
// 定义批量扣除的用户和金额列表
|
||
// Map<Long, Long> batchDeductMap = new HashMap<>();
|
||
// batchDeductMap.put(1957345312961527809L, 1L);
|
||
// batchDeductMap.put(1989287471839113218L, 1L);
|
||
// 可以继续添加更多用户...
|
||
|
||
System.out.println("========== 开始批量扣除 ==========");
|
||
System.out.println("批量扣除总数: " + batchDeductMap.size());
|
||
System.out.println();
|
||
|
||
// 统计数据
|
||
int successCount = 0; // 成功扣除的数量
|
||
int failCount = 0; // 失败的数量
|
||
int skipCount = 0; // 跳过的数量(目标值不足)
|
||
long totalDeductValue = 0L; // 总扣除金额
|
||
List<String> failedUsers = new ArrayList<>(); // 失败的用户列表
|
||
|
||
// 循环批量扣除
|
||
for (Map.Entry<Long, Long> entry : batchDeductMap.entrySet()) {
|
||
Long userId = entry.getKey();
|
||
Long deductValue = entry.getValue();
|
||
|
||
System.out.println("---------- 处理用户: " + userId + " ----------");
|
||
System.out.println("扣除金额: " + deductValue);
|
||
|
||
try {
|
||
boolean result = deductSingleAnchorTarget(userId, deductValue);
|
||
if (result) {
|
||
successCount++;
|
||
totalDeductValue += deductValue;
|
||
System.out.println("✓ 用户 " + userId + " 扣除成功");
|
||
} else {
|
||
skipCount++;
|
||
System.out.println("⊘ 用户 " + userId + " 跳过(目标值不足或无未结算工单)");
|
||
}
|
||
} catch (Exception e) {
|
||
failCount++;
|
||
failedUsers.add(userId + " (错误: " + e.getMessage() + ")");
|
||
System.out.println("✗ 用户 " + userId + " 扣除失败: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
|
||
System.out.println();
|
||
}
|
||
|
||
// 打印统计结果
|
||
System.out.println("========== 批量扣除完成 ==========");
|
||
System.out.println("总处理数: " + batchDeductMap.size());
|
||
System.out.println("成功数: " + successCount);
|
||
System.out.println("跳过数: " + skipCount);
|
||
System.out.println("失败数: " + failCount);
|
||
System.out.println("总扣除金额: " + totalDeductValue);
|
||
System.out.println("成功率: " + String.format("%.2f%%", (successCount * 100.0 / batchDeductMap.size())));
|
||
|
||
if (!failedUsers.isEmpty()) {
|
||
System.out.println("\n失败用户列表:");
|
||
failedUsers.forEach(user -> System.out.println(" - " + user));
|
||
}
|
||
|
||
System.out.println("========================================");
|
||
}
|
||
|
||
/**
|
||
* 单个主播目标扣除(从原方法提取出来)
|
||
* @param userId 用户ID
|
||
* @param deductValue 扣除金额
|
||
* @return true-成功扣除, false-跳过(目标值不足或无未结算工单)
|
||
*/
|
||
private boolean deductSingleAnchorTarget(Long userId, Long deductValue) {
|
||
TeamMemberWorkQryCmd cmd = new TeamMemberWorkQryCmd();
|
||
cmd.setMemberUserId(userId);
|
||
cmd.setSysOrigin("BZIZI");
|
||
List<TeamMemberWorkDTO> execute = listMemberWorkDecay.execute(cmd);
|
||
|
||
// 1. 筛选 billStatus = UNPAID 的数据
|
||
List<TeamMemberWorkDTO> unpaidList = execute.stream()
|
||
.filter(work -> "UNPAID".equals(work.getBillStatus()))
|
||
.limit(1)
|
||
.toList();
|
||
|
||
System.out.println("未结算的工单数量: " + unpaidList.size());
|
||
|
||
if (unpaidList.isEmpty()) {
|
||
return false;
|
||
}
|
||
|
||
for (TeamMemberWorkDTO work : unpaidList) {
|
||
// 2. 统计 dailyTargets 的 acceptGiftValue 的和
|
||
Long totalAcceptGiftValue = work.getTarget().getDailyTargets().stream()
|
||
.mapToLong(TeamMemberWorkDailyTargetDTO::getAcceptGiftValue)
|
||
.sum();
|
||
|
||
System.out.println("工单ID: " + work.getId() + ", 总收礼物价值: " + totalAcceptGiftValue);
|
||
|
||
// 3. 检查目标值够不够扣
|
||
if (totalAcceptGiftValue < deductValue) {
|
||
System.out.println("目标值不足,无法扣除。需要: " + deductValue + ", 当前: " + totalAcceptGiftValue);
|
||
return false;
|
||
}
|
||
|
||
// 4. 从第一天开始扣除
|
||
Long remainingDeduct = deductValue;
|
||
List<TeamMemberWorkDailyTargetDTO> dailyTargets = work.getTarget().getDailyTargets();
|
||
boolean hasModified = false; // 标记是否有修改
|
||
|
||
for (int i = 0; i < dailyTargets.size(); i++) {
|
||
TeamMemberWorkDailyTargetDTO dailyTarget = dailyTargets.get(i);
|
||
Long currentValue = dailyTarget.getAcceptGiftValue();
|
||
|
||
if (remainingDeduct <= 0) {
|
||
break;
|
||
}
|
||
|
||
if (currentValue > 0) { // 只有当前值大于0时才可能修改
|
||
hasModified = true; // 标记为已修改
|
||
|
||
if (currentValue >= remainingDeduct) {
|
||
// 当前天的值足够扣除剩余部分
|
||
dailyTarget.setAcceptGiftValue(currentValue - remainingDeduct);
|
||
System.out.println("日期 " + dailyTarget.getDateNumber() + " 扣除: " + remainingDeduct + ", 剩余: " + (currentValue - remainingDeduct));
|
||
remainingDeduct = 0L;
|
||
} else {
|
||
// 当前天的值不够,全部扣除
|
||
dailyTarget.setAcceptGiftValue(0L);
|
||
remainingDeduct -= currentValue;
|
||
System.out.println("日期 " + dailyTarget.getDateNumber() + " 扣除: " + currentValue + ", 剩余需扣除: " + remainingDeduct);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 5. 只有当有修改时才更新 MongoDB
|
||
if (hasModified) {
|
||
updateTeamMemberTarget(work.getId(), dailyTargets);
|
||
System.out.println("工单 " + work.getId() + " 扣除完成,已更新到MongoDB");
|
||
return true;
|
||
} else {
|
||
System.out.println("工单 " + work.getId() + " 无需修改,跳过更新");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 更新 MongoDB 中的 TeamMemberTarget
|
||
* @param timeId 工单ID
|
||
* @param dailyTargets 更新后的每日目标列表
|
||
*/
|
||
private void updateTeamMemberTarget(Long timeId, List<TeamMemberWorkDailyTargetDTO> dailyTargets) {
|
||
Query query = new Query(Criteria.where("timeId").is(timeId));
|
||
|
||
// 更新 target.dailyTargets 数组
|
||
for (int i = 0; i < dailyTargets.size(); i++) {
|
||
TeamMemberWorkDailyTargetDTO dailyTarget = dailyTargets.get(i);
|
||
|
||
mongoTemplate.updateFirst(query,
|
||
new Update()
|
||
.set("updateTime", TimestampUtils.now())
|
||
.set("dailyTargets.$[i].acceptGiftValue", dailyTarget.getAcceptGiftValue())
|
||
.set("dailyTargets.$[i].updateTime", TimestampUtils.now())
|
||
.filterArray(Criteria.where("i.dateNumber").is(dailyTarget.getDateNumber())),
|
||
TeamMemberTarget.class);
|
||
}
|
||
}
|
||
|
||
}
|