bd 详情接口修改

This commit is contained in:
tianfeng 2025-10-30 21:04:43 +08:00
parent aefcf81c5d
commit ff420940c8
12 changed files with 558 additions and 8 deletions

View File

@ -6,10 +6,8 @@ import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.web.controller.BaseController;
import com.red.circle.other.app.dto.clientobject.team.*;
import com.red.circle.other.app.dto.cmd.activity.LotteryWithdrawCmd;
import com.red.circle.other.app.dto.cmd.team.BdInviteQryCmd;
import com.red.circle.other.app.dto.cmd.team.DbInviteAgentCmd;
import com.red.circle.other.app.dto.cmd.team.DbInviteMessageProcessCmd;
import com.red.circle.other.app.dto.cmd.team.DbLeaderInviteBdCmd;
import com.red.circle.other.app.dto.cmd.team.*;
import com.red.circle.other.app.service.team.TeamBdHistoryService;
import com.red.circle.other.app.service.team.TeamBdService;
import com.red.circle.other.app.service.TeamBdBillService;
import com.red.circle.other.app.dto.cmd.TeamBdMemberBillCmd;
@ -47,6 +45,7 @@ public class TeamBdRestController extends BaseController {
private final TeamBdService teamBdService;
private final TeamBdBillService teamBdBillService;
private final TeamBdHistoryService teamBdHistoryService;
/**
* 获得bd角色.
@ -299,5 +298,35 @@ public class TeamBdRestController extends BaseController {
teamBdBillService.applyWithdraw(cmd);
}
/**
* 查询BD历史记录
*
* @param cmd 查询命令
* @return BD历史记录汇总
* @eo.name 查询BD历史记录
* @eo.url /history
* @eo.method get
* @eo.request-type formdata
*/
@GetMapping("/history")
public BdHistorySummaryCO queryBdHistory(@Validated BdHistoryQryCmd cmd) {
return teamBdHistoryService.queryBdHistory(cmd);
}
/**
* 查询BD Leader历史记录
*
* @param cmd 查询命令
* @return BD Leader历史记录汇总
* @eo.name 查询BD Leader历史记录
* @eo.url /leader/history
* @eo.method get
* @eo.request-type formdata
*/
@GetMapping("/leader/history")
public BdLeaderHistorySummaryCO queryBdLeaderHistory(@Validated BdLeaderHistoryQryCmd cmd) {
return teamBdHistoryService.queryBdLeaderHistory(cmd);
}
}

View File

@ -59,7 +59,7 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService
log.warn("开始处理所有 BD 工资结算,结算周期:{}", billBelong);
// 查询所有 BD
List<BusinessDevelopmentTeam> allBdTeams = businessDevelopmentTeamService.listAll();
List<BusinessDevelopmentTeam> allBdTeams = businessDevelopmentTeamService.listByBdUserId(1976098223186104322L);
if (CollectionUtils.isEmpty(allBdTeams)) {
log.warn("没有找到任何 BD 数据");
@ -117,7 +117,7 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService
if (record.getSettlementSalary() != null && record.getSettlementSalary().compareTo(BigDecimal.ZERO) > 0) {
try {
// 调用钱包服务发放工资
issueSalary(bdUserId, record);
// issueSalary(bdUserId, record);
// 更新状态为成功
bdSalarySettlementRecordService.updateStatus(record.getId(), BdSettlementStatus.SUCCESS, null);

View File

@ -0,0 +1,233 @@
package com.red.circle.other.app.service.team;
import com.red.circle.other.app.dto.clientobject.team.*;
import com.red.circle.other.app.dto.cmd.team.BdHistoryQryCmd;
import com.red.circle.other.app.dto.cmd.team.BdLeaderHistoryQryCmd;
import com.red.circle.other.infra.database.mongo.entity.bd.BdLeaderSalarySettlementRecord;
import com.red.circle.other.infra.database.mongo.entity.bd.BdSalarySettlementRecord;
import com.red.circle.other.infra.enums.BdSettlementStatus;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.text.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* BD历史记录服务实现
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class TeamBdHistoryServiceImpl implements TeamBdHistoryService {
private final MongoTemplate mongoTemplate;
@Override
public BdHistorySummaryCO queryBdHistory(BdHistoryQryCmd cmd) {
Long userId = cmd.getReqUserId();
String sysOrigin = cmd.getReqSysOrigin().getOrigin();
// 构建查询条件
Query query = new Query();
query.addCriteria(Criteria.where("bdUserId").is(userId));
query.addCriteria(Criteria.where("sysOrigin").is(sysOrigin));
// 如果指定了状态添加状态过滤
if (StringUtils.isNotBlank(cmd.getStatus())) {
query.addCriteria(Criteria.where("status").is(BdSettlementStatus.valueOf(cmd.getStatus())));
}
// 按结算周期降序排序
query.with(org.springframework.data.domain.Sort.by(
org.springframework.data.domain.Sort.Direction.DESC, "billBelong"));
// 查询记录
List<BdSalarySettlementRecord> records = mongoTemplate.find(
query, BdSalarySettlementRecord.class);
// 构建返回结果
BdHistorySummaryCO summary = new BdHistorySummaryCO();
if (CollectionUtils.isEmpty(records)) {
summary.setTotalIncome(BigDecimal.ZERO);
summary.setPreviousPeriodIncome(BigDecimal.ZERO);
summary.setIncomeDetails(new ArrayList<>());
return summary;
}
// 计算总收入SUCCESS状态的记录
BigDecimal totalIncome = records.stream()
.filter(r -> BdSettlementStatus.SUCCESS.equals(r.getStatus()))
.map(BdSalarySettlementRecord::getSettlementSalary)
.filter(java.util.Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 获取上个周期收入最近的一条SUCCESS记录
BigDecimal previousPeriodIncome = records.stream()
.filter(r -> BdSettlementStatus.SUCCESS.equals(r.getStatus()))
.findFirst()
.map(BdSalarySettlementRecord::getSettlementSalary)
.orElse(BigDecimal.ZERO);
// 转换为DTO列表
List<BdHistoryCO> incomeDetails = records.stream()
.map(this::convertToBdHistoryCO)
.toList();
summary.setTotalIncome(totalIncome);
summary.setPreviousPeriodIncome(previousPeriodIncome);
summary.setIncomeDetails(incomeDetails);
return summary;
}
@Override
public BdLeaderHistorySummaryCO queryBdLeaderHistory(BdLeaderHistoryQryCmd cmd) {
Long userId = cmd.getReqUserId();
String sysOrigin = cmd.getReqSysOrigin().getOrigin();
// 构建查询条件
Query query = new Query();
query.addCriteria(Criteria.where("bdLeaderUserId").is(userId));
query.addCriteria(Criteria.where("sysOrigin").is(sysOrigin));
// 如果指定了状态添加状态过滤
if (StringUtils.isNotBlank(cmd.getStatus())) {
query.addCriteria(Criteria.where("status").is(BdSettlementStatus.valueOf(cmd.getStatus())));
}
// 按结算周期降序排序
query.with(org.springframework.data.domain.Sort.by(
org.springframework.data.domain.Sort.Direction.DESC, "billBelong"));
// 查询记录
List<BdLeaderSalarySettlementRecord> records = mongoTemplate.find(
query, BdLeaderSalarySettlementRecord.class);
// 构建返回结果
BdLeaderHistorySummaryCO summary = new BdLeaderHistorySummaryCO();
if (CollectionUtils.isEmpty(records)) {
summary.setTotalIncome(BigDecimal.ZERO);
summary.setPreviousPeriodIncome(BigDecimal.ZERO);
summary.setIncomeDetails(new ArrayList<>());
return summary;
}
// 计算总收入SUCCESS状态的记录
BigDecimal totalIncome = records.stream()
.filter(r -> BdSettlementStatus.SUCCESS.equals(r.getStatus()))
.map(BdLeaderSalarySettlementRecord::getSettlementSalary)
.filter(java.util.Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 获取上个周期收入最近的一条SUCCESS记录
BigDecimal previousPeriodIncome = records.stream()
.filter(r -> BdSettlementStatus.SUCCESS.equals(r.getStatus()))
.findFirst()
.map(BdLeaderSalarySettlementRecord::getSettlementSalary)
.orElse(BigDecimal.ZERO);
// 转换为DTO列表
List<BdLeaderHistoryCO> incomeDetails = records.stream()
.map(this::convertToBdLeaderHistoryCO)
.toList();
summary.setTotalIncome(totalIncome);
summary.setPreviousPeriodIncome(previousPeriodIncome);
summary.setIncomeDetails(incomeDetails);
return summary;
}
/**
* 转换BD结算记录为DTO
*/
private BdHistoryCO convertToBdHistoryCO(BdSalarySettlementRecord record) {
BdHistoryCO co = new BdHistoryCO();
co.setPeriod(formatPeriod(record.getBillBelong()));
co.setBillTitle(record.getBillTitle());
co.setAgencyNumber(record.getAgencyNumber());
co.setTeamSalaryAmount(record.getTeamSalaryAmount());
co.setTeamRechargeAmount(record.getTeamRechargeAmount());
co.setSettlementSalary(record.getSettlementSalary());
co.setStatus(record.getStatus() != null ? record.getStatus().name() : null);
co.setStatusText(getStatusText(record.getStatus()));
co.setHitPolicyType(record.getHitPolicyType() != null ? record.getHitPolicyType().name() : null);
co.setHitLevel(record.getHitLevel());
co.setCommissionRate(record.getCommissionRate());
return co;
}
/**
* 转换BD Leader结算记录为DTO
*/
private BdLeaderHistoryCO convertToBdLeaderHistoryCO(BdLeaderSalarySettlementRecord record) {
BdLeaderHistoryCO co = new BdLeaderHistoryCO();
co.setPeriod(formatPeriod(record.getBillBelong()));
co.setBillTitle(record.getBillTitle());
co.setBdNumber(record.getBdNumber());
co.setTeamSalaryAmount(record.getTeamSalaryAmount());
co.setBasicSalary(record.getBasicSalary());
co.setRewardAmount(record.getRewardAmount());
co.setSettlementSalary(record.getSettlementSalary());
co.setStatus(record.getStatus() != null ? record.getStatus().name() : null);
co.setStatusText(getStatusText(record.getStatus()));
co.setHitLevel(record.getHitLevel());
co.setRewardEligible(record.getRewardEligible());
co.setNewRechargeAgentCount(record.getNewRechargeAgentCount());
return co;
}
/**
* 格式化结算周期为日期范围
* 例如202501 -> 2025.10.01-2025.10.15
* 202502 -> 2025.10.16-2025.10.31
*/
private String formatPeriod(Integer billBelong) {
if (billBelong == null) {
return "";
}
int year = billBelong / 100;
int period = billBelong % 100;
int month = (period + 1) / 2;
boolean isFirstHalf = (period % 2 == 1);
LocalDate startDate, endDate;
if (isFirstHalf) {
startDate = LocalDate.of(year, month, 1);
endDate = LocalDate.of(year, month, 15);
} else {
startDate = LocalDate.of(year, month, 16);
endDate = LocalDate.of(year, month, startDate.lengthOfMonth());
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd");
return startDate.format(formatter) + "-" + endDate.format(formatter);
}
/**
* 获取状态显示文本
*/
private String getStatusText(BdSettlementStatus status) {
if (status == null) {
return "";
}
return switch (status) {
case PENDING -> "In Progress";
case SUCCESS -> "Completed";
case FAILED -> "Failed";
};
}
}

View File

@ -0,0 +1,69 @@
package com.red.circle.other.app.dto.clientobject.team;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
/**
* BD历史记录
*/
@Data
@Accessors(chain = true)
public class BdHistoryCO {
/**
* 结算周期格式2025.10.16-2025.10.31
*/
private String period;
/**
* 结算周期标题
*/
private String billTitle;
/**
* Agent数量
*/
private Integer agencyNumber;
/**
* 团队工资美元
*/
private BigDecimal teamSalaryAmount;
/**
* 团队充值美元
*/
private BigDecimal teamRechargeAmount;
/**
* 最终结算工资美元
*/
private BigDecimal settlementSalary;
/**
* 结算状态: PENDING(In Progress) | SUCCESS(Completed) | FAILED
*/
private String status;
/**
* 结算状态显示文本
*/
private String statusText;
/**
* 命中的政策类型
*/
private String hitPolicyType;
/**
* 命中的等级
*/
private Integer hitLevel;
/**
* 提成比例
*/
private BigDecimal commissionRate;
}

View File

@ -0,0 +1,30 @@
package com.red.circle.other.app.dto.clientobject.team;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.List;
/**
* BD历史记录汇总
*/
@Data
@Accessors(chain = true)
public class BdHistorySummaryCO {
/**
* 总收入美元
*/
private BigDecimal totalIncome;
/**
* 上个周期收入美元
*/
private BigDecimal previousPeriodIncome;
/**
* 收入明细列表
*/
private List<BdHistoryCO> incomeDetails;
}

View File

@ -0,0 +1,74 @@
package com.red.circle.other.app.dto.clientobject.team;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
/**
* BD Leader历史记录
*/
@Data
@Accessors(chain = true)
public class BdLeaderHistoryCO {
/**
* 结算周期格式2025.10.16-2025.10.31
*/
private String period;
/**
* 结算周期标题
*/
private String billTitle;
/**
* BD数量
*/
private Integer bdNumber;
/**
* 团队工资美元
*/
private BigDecimal teamSalaryAmount;
/**
* 基础工资美元
*/
private BigDecimal basicSalary;
/**
* 奖励金额美元
*/
private BigDecimal rewardAmount;
/**
* 最终结算工资美元
*/
private BigDecimal settlementSalary;
/**
* 结算状态: PENDING(In Progress) | SUCCESS(Completed) | FAILED
*/
private String status;
/**
* 结算状态显示文本
*/
private String statusText;
/**
* 命中的等级
*/
private Integer hitLevel;
/**
* 是否满足奖励条件
*/
private Boolean rewardEligible;
/**
* 新增充值代理数量
*/
private Integer newRechargeAgentCount;
}

View File

@ -0,0 +1,30 @@
package com.red.circle.other.app.dto.clientobject.team;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.List;
/**
* BD Leader历史记录汇总
*/
@Data
@Accessors(chain = true)
public class BdLeaderHistorySummaryCO {
/**
* 总收入美元
*/
private BigDecimal totalIncome;
/**
* 上个周期收入美元
*/
private BigDecimal previousPeriodIncome;
/**
* 收入明细列表
*/
private List<BdLeaderHistoryCO> incomeDetails;
}

View File

@ -0,0 +1,18 @@
package com.red.circle.other.app.dto.cmd.team;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* BD历史记录查询命令
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class BdHistoryQryCmd extends AppExtCommand {
/**
* 结算状态可选: PENDING | SUCCESS | FAILED
*/
private String status;
}

View File

@ -0,0 +1,18 @@
package com.red.circle.other.app.dto.cmd.team;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* BD Leader历史记录查询命令
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class BdLeaderHistoryQryCmd extends AppExtCommand {
/**
* 结算状态可选: PENDING | SUCCESS | FAILED
*/
private String status;
}

View File

@ -0,0 +1,22 @@
package com.red.circle.other.app.service.team;
import com.red.circle.other.app.dto.clientobject.team.BdHistorySummaryCO;
import com.red.circle.other.app.dto.clientobject.team.BdLeaderHistorySummaryCO;
import com.red.circle.other.app.dto.cmd.team.BdHistoryQryCmd;
import com.red.circle.other.app.dto.cmd.team.BdLeaderHistoryQryCmd;
/**
* BD历史记录服务
*/
public interface TeamBdHistoryService {
/**
* 查询BD历史记录
*/
BdHistorySummaryCO queryBdHistory(BdHistoryQryCmd cmd);
/**
* 查询BD Leader历史记录
*/
BdLeaderHistorySummaryCO queryBdLeaderHistory(BdLeaderHistoryQryCmd cmd);
}

View File

@ -62,14 +62,14 @@ public class BdSalaryPolicyServiceImpl implements BdSalaryPolicyService {
@Override
public List<BdSalaryPolicy> listEnabledByType(BdPolicyType policyType) {
Query query = new Query(Criteria.where("enabled").is(true)
.and("policyType").is(policyType));
.and("policyType").is(policyType.name()));
query.with(Sort.by(Sort.Order.asc("level")));
return mongoTemplate.find(query, BdSalaryPolicy.class);
}
@Override
public BdSalaryPolicy getByTypeAndLevel(BdPolicyType policyType, Integer level) {
Query query = new Query(Criteria.where("policyType").is(policyType)
Query query = new Query(Criteria.where("policyType").is(policyType.name())
.and("level").is(level)
.and("enabled").is(true));
return mongoTemplate.findOne(query, BdSalaryPolicy.class);

View File

@ -0,0 +1,27 @@
import com.red.circle.OtherServiceApplication;
import com.red.circle.other.app.scheduler.BdSalarySettlementTask;
import com.red.circle.other.app.scheduler.TeamBillTask;
import com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils;
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.test.context.junit4.SpringRunner;
@SpringBootTest(classes = OtherServiceApplication.class)
@RunWith(SpringRunner.class)
public class BdSettlementTest {
@Autowired
private BdSalarySettlementTask bdSalarySettlementTask;
@Test
public void testBdSettlement() {
Integer billBelong = TeamBillCycleUtils.getCalcBillBelong();
bdSalarySettlementTask.processBdSalarySettlementTest(billBelong);
}
}