半月结算处理

This commit is contained in:
tianfeng 2025-10-13 16:56:04 +08:00
parent 5e2d38c93e
commit a4861816c0
7 changed files with 104 additions and 35 deletions

View File

@ -134,7 +134,7 @@ public class TestRestController extends BaseController {
@PostMapping("/processTeamMonthBill") @PostMapping("/processTeamMonthBill")
public void processTeamMonthBill() { public void processTeamMonthBill() {
teamBillTask.processTeamMonthBill(); teamBillTask.processTeamHalfMonthBill();
} }
@PostMapping("/activity/send/game") @PostMapping("/activity/send/game")

View File

@ -20,6 +20,8 @@ import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import static com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils.getCalcBillBelong;
/** /**
* 历史app内主播中心 数据统计. * 历史app内主播中心 数据统计.
* *

View File

@ -175,7 +175,7 @@ public class GiftAnchorCountStrategy implements GiftStrategy {
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
log.warn("异步同步钻石情况{}", teamIds); log.warn("异步同步钻石情况{}", teamIds);
initProfilesDiamond(teamIds, giftAcceptUsers); // initProfilesDiamond(teamIds, giftAcceptUsers);
}); });
} }
@ -387,13 +387,6 @@ public class GiftAnchorCountStrategy implements GiftStrategy {
} }
private void countTarget(GiftGiveRunningWater runningWater, GiftAcceptUser acceptAnchorUser) { private void countTarget(GiftGiveRunningWater runningWater, GiftAcceptUser acceptAnchorUser) {
// 2023/12/20 印度特色房间 礼物不进目标
List<String> ignoreRooms = Arrays.asList("1655084280806866945",
"1738118365374660610");
if (ignoreRooms.contains(runningWater.getOriginId())) {
return;
}
// 累计目标 // 累计目标
TeamTargetBillRes teamTargetBillRes = teamTargetCommon.incrementGiftValue( TeamTargetBillRes teamTargetBillRes = teamTargetCommon.incrementGiftValue(
acceptAnchorUser.getAcceptUserId(), acceptAnchorUser.getAcceptUserId(),

View File

@ -10,7 +10,11 @@ import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileSe
import com.red.circle.other.infra.utils.ZonedDateTimeUtils; import com.red.circle.other.infra.utils.ZonedDateTimeUtils;
import com.red.circle.other.inner.model.cmd.team.TeamBillCmd; import com.red.circle.other.inner.model.cmd.team.TeamBillCmd;
import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.date.TimestampUtils;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
@ -32,17 +36,21 @@ public class TeamBillTask {
private final GiftGiveRunningWaterService giftGiveRunningWaterService; private final GiftGiveRunningWaterService giftGiveRunningWaterService;
/** /**
* 每月1号 0点执行. * 每月1号和16号 0点执行半月结算
*/ */
// 每月最后一天 0点执行 @Scheduled(cron = "0 0 0 1,16 * ?", zone = "Asia/Riyadh")
// @Scheduled(cron = "0 0 0 L * ?", zone = "Asia/Riyadh") @TaskCacheLock(key = "PROCESS_TEAM_BILL_HALF_MONTH", expireSecond = 86400)
@Scheduled(cron = "0 0 0 1 * ?", zone = "Asia/Riyadh") public void processTeamHalfMonthBill() {
@TaskCacheLock(key = "PROCESS_TEAM_BILL", expireSecond = 86400)
public void processTeamMonthBill() {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
log.info("exec process_team_bill start"); log.info("exec process_team_half_month_bill start");
// 判断是上半月还是下半月
LocalDate now = LocalDate.now(ZoneId.of("Asia/Riyadh"));
String billPeriod = now.getDayOfMonth() == 1 ? "first_half" : "second_half";
processTeamBill(); processTeamBill();
log.info("exec process_team_bill end with {}",System.currentTimeMillis()-startTime); log.info("exec process_team_half_month_bill end with {}",
System.currentTimeMillis() - startTime);
} }
public void processTeamMonthBillTest() { public void processTeamMonthBillTest() {

View File

@ -23,6 +23,8 @@ import java.util.Objects;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import static com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils.getCalcBillBelong;
/** /**
* 房间主播管理. * 房间主播管理.
* *
@ -120,7 +122,7 @@ public class TeamTargetCommon {
TeamMember teamMember = teamMemberService.getByMemberId(userId); TeamMember teamMember = teamMemberService.getByMemberId(userId);
if (Objects.isNull(teamMember)) { if (Objects.isNull(teamMember)) {
return TeamTargetBillRes.of((long) ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt(), return TeamTargetBillRes.of((long) getCalcBillBelong(),
Boolean.FALSE); Boolean.FALSE);
} }
@ -138,13 +140,13 @@ public class TeamTargetCommon {
} }
// 锁定期间进来的数据一律当做不是主播处理 // 锁定期间进来的数据一律当做不是主播处理
return TeamTargetBillRes.of((long) ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt(), return TeamTargetBillRes.of((long) getCalcBillBelong(),
Boolean.FALSE); Boolean.FALSE);
} }
// 创建成员每日目标单据 // 创建成员每日目标单据
teamMemberTargetService teamMemberTargetService
.createDailyWorkTarget(userId, ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()); .createDailyWorkTarget(userId, getCalcBillBelong());
return consumer.apply(); return consumer.apply();
} }
@ -155,8 +157,8 @@ public class TeamTargetCommon {
.setTimeId(IdWorkerUtils.getId()) .setTimeId(IdWorkerUtils.getId())
.setSysOrigin(teamMember.getSysOrigin()) .setSysOrigin(teamMember.getSysOrigin())
.setTeamId(teamMember.getTeamId()) .setTeamId(teamMember.getTeamId())
.setBillBelong(ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()) .setBillBelong(getCalcBillBelong())
.setBillTitle(ZonedDateTimeAsiaRiyadhUtils.nowFormat(DateFormatConstant.MM_SLASH_YYYY)) .setBillTitle(getCalcBillBelong().toString())
.setUserId(teamMember.getMemberId()) .setUserId(teamMember.getMemberId())
.setStatus(Boolean.TRUE.equals(getOpenDailyAutoSalary(teamMember)) .setStatus(Boolean.TRUE.equals(getOpenDailyAutoSalary(teamMember))
? TeamMemberTargetStatus.AUTO : TeamMemberTargetStatus.NOT_RECORDED) ? TeamMemberTargetStatus.AUTO : TeamMemberTargetStatus.NOT_RECORDED)
@ -178,7 +180,7 @@ public class TeamTargetCommon {
private Boolean existsBillTarget(Long userId) { private Boolean existsBillTarget(Long userId) {
return teamMemberTargetService return teamMemberTargetService
.existsBillTarget(userId, ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()); .existsBillTarget(userId, getCalcBillBelong());
} }
private Boolean getOpenDailyAutoSalary(TeamMember teamMember) { private Boolean getOpenDailyAutoSalary(TeamMember teamMember) {

View File

@ -12,11 +12,14 @@ import com.red.circle.other.inner.enums.team.TeamMemberTargetIndex;
import com.red.circle.tool.core.collection.CollectionUtils; import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.num.NumUtils; import com.red.circle.tool.core.num.NumUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -472,4 +475,31 @@ public final class TeamBillCycleUtils {
}).filter(Objects::nonNull).collect(Collectors.toList()); }).filter(Objects::nonNull).collect(Collectors.toList());
} }
public static Integer getCalcBillBelong() {
LocalDate now = ZonedDateTimeAsiaRiyadhUtils.now().toLocalDate();
return calculateCurrentBillBelong(now);
}
/**
* 计算当前账期的 billBelong
* 规则
* - 1-15号当前账期是本月1号20251001
* - 16-月末当前账期是本月16号20251016
*/
private static Integer calculateCurrentBillBelong(LocalDate now) {
int day = now.getDayOfMonth();
LocalDate billDate;
if (day < 16) {
// 当前是上半月账期开始日期是本月1号
billDate = now.withDayOfMonth(1);
} else {
// 当前是下半月账期开始日期是本月16号
billDate = now.withDayOfMonth(16);
}
return Integer.parseInt(billDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
}
} }

View File

@ -18,6 +18,7 @@ import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils; import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils; import com.red.circle.tool.core.text.StringUtils;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -33,6 +34,8 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import static com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils.getCalcBillBelong;
/** /**
* 账单服务. * 账单服务.
* *
@ -83,15 +86,29 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
@Override @Override
public Map<Long, TeamBillCycle> mapLastMonthByTeamIds(Set<Long> teamIds) { public Map<Long, TeamBillCycle> mapLastMonthByTeamIds(Set<Long> teamIds) {
if (CollectionUtils.isEmpty(teamIds)) { if (CollectionUtils.isEmpty(teamIds)) {
return Maps.newHashMap(); return Maps.newHashMap();
} }
int lastMonthYYYYMM = Integer.parseInt(
ZonedDateTimeAsiaRiyadhUtils.now().minusMonths(1)
.format(DateTimeFormatter.ofPattern(DateFormatConstant.yyyyMM)));
// 计算8位格式的范围yyyyMM01 yyyyMM31
int rangeStart = lastMonthYYYYMM * 100; // 例如202509 * 100 = 20250900
int rangeEnd = lastMonthYYYYMM * 100 + 99; // 例如202509 * 100 + 99 = 20250999
// 匹配条件
// 1. billBelong = 202509 (6位旧格式)
// 2. billBelong 20250901 20250999 之间 (8位新格式)
Criteria criteria = new Criteria().orOperator(
Criteria.where("billBelong").is(lastMonthYYYYMM),
Criteria.where("billBelong").gte(rangeStart).lte(rangeEnd)
);
List<TeamBillCycle> teamBillCycles = mongoTemplate.find( List<TeamBillCycle> teamBillCycles = mongoTemplate.find(
Query.query(Criteria.where("teamId").in(teamIds) Query.query(criteria
.and("billBelong").is(Integer.parseInt(ZonedDateTimeAsiaRiyadhUtils.now().minusMonths(1) .and("teamId").in(teamIds)
.format(DateTimeFormatter.ofPattern(DateFormatConstant.yyyyMM))))
.and("status").is(TeamBillCycleStatus.SETTLED)), .and("status").is(TeamBillCycleStatus.SETTLED)),
TeamBillCycle.class); TeamBillCycle.class);
@ -99,7 +116,8 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
return Maps.newHashMap(); return Maps.newHashMap();
} }
return teamBillCycles.stream().collect(Collectors.toMap(TeamBillCycle::getTeamId, v -> v)); return teamBillCycles.stream()
.collect(Collectors.toMap(TeamBillCycle::getTeamId, v -> v));
} }
@ -116,8 +134,8 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
.setRegion(param.getRegion()) .setRegion(param.getRegion())
.setInternalRemarks(Lists.newArrayList()) .setInternalRemarks(Lists.newArrayList())
.setSettleResult(null) .setSettleResult(null)
.setBillBelong(ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()) .setBillBelong(getCalcBillBelong())
.setBillTitle(ZonedDateTimeAsiaRiyadhUtils.nowFormat(DateFormatConstant.MM_SLASH_YYYY)) .setBillTitle(getCalcBillBelong().toString())
.setCreateTime(param.getOperationTime()) .setCreateTime(param.getOperationTime())
.setUpdateTime(TimestampUtils.now()) .setUpdateTime(TimestampUtils.now())
.setCreateUser(param.getOperationBackUser()) .setCreateUser(param.getOperationBackUser())
@ -127,10 +145,23 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
@Override @Override
public List<TeamBillCycle> listLastMonthByTeamIds(Set<Long> teamIds) { public List<TeamBillCycle> listLastMonthByTeamIds(Set<Long> teamIds) {
int currentYearMonth = ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt();
// 计算8位格式的范围yyyyMM01 yyyyMM99
int rangeStart = currentYearMonth * 100; // 例如202510 * 100 = 20251000
int rangeEnd = currentYearMonth * 100 + 99; // 例如202510 * 100 + 99 = 20251099
// 匹配条件
// 1. billBelong = 202510 (6位旧格式)
// 2. billBelong 20251001 20251099 之间 (8位新格式)
Criteria criteria = new Criteria().orOperator(
Criteria.where("billBelong").is(currentYearMonth),
Criteria.where("billBelong").gte(rangeStart).lte(rangeEnd)
);
return mongoTemplate.find( return mongoTemplate.find(
Query.query(Criteria.where("teamId").in(teamIds) Query.query(criteria
.and("billBelong").is(ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()) .and("teamId").in(teamIds)
.and("status").is(TeamBillCycleStatus.SETTLED)), .and("status").is(TeamBillCycleStatus.SETTLED)),
TeamBillCycle.class); TeamBillCycle.class);
} }
@ -183,7 +214,7 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
return mongoPrimaryService.exists("team_bill_cycle", return mongoPrimaryService.exists("team_bill_cycle",
Filters.and( Filters.and(
Filters.eq("teamId", teamId), Filters.eq("teamId", teamId),
Filters.eq("billBelong", ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()) Filters.eq("billBelong", getCalcBillBelong())
) )
); );
} }
@ -340,10 +371,13 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
@Override @Override
public void billStatusPayOut() { public void billStatusPayOut() {
// 进行中 -> 出单 // 计算当前账期的 billBelong
Integer currentBillBelong = getCalcBillBelong();
// 将小于当前账期的 UNPAID 状态改为 PAY_OUT
mongoTemplate.updateMulti( mongoTemplate.updateMulti(
Query.query( Query.query(
Criteria.where("billBelong").lt(ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt()) Criteria.where("billBelong").lt(currentBillBelong)
.and("status").is(TeamBillCycleStatus.UNPAID)), .and("status").is(TeamBillCycleStatus.UNPAID)),
new Update() new Update()
.set("updateTime", TimestampUtils.now()) .set("updateTime", TimestampUtils.now())