This commit is contained in:
hy001 2026-05-18 21:57:22 +08:00
parent d9d690e53d
commit 32a1094edc
2 changed files with 64 additions and 10 deletions

View File

@ -58,6 +58,10 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
private static final String COLLECTION_GIFT_GIVE_RUNNING_WATER = "gift_give_running_water";
private static final String COLLECTION_USER_DAILY_ACTIVE_LOG = "user_daily_active_log";
private static final String COLLECTION_USER_BANK_RUNNING_WATER = "user_bank_running_water";
private static final String BANK_EXCHANGE_GOLD_EVENT = "EXCHANGE_GOLD_COINS";
private static final String BANK_TRANSFER_GOLD_EVENT = "TRANSFER_GOLD";
private static final int RECEIPT_TYPE_EXPENDITURE = 1;
private static final String PERIOD_ALL = "ALL";
private static final ZoneId STORAGE_ZONE_ID = ZoneId.of("Asia/Riyadh");
private static final ZoneId DEFAULT_STAT_ZONE_ID = STORAGE_ZONE_ID;
@ -81,6 +85,7 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
condition.countryKeyword, condition.statTimezone, condition.sysOrigin));
} else {
mergeLiveSql(rows, condition);
mergeBankSalaryExchange(rows, condition);
}
if (usePrecomputedMetrics && condition.shouldOverlayLiveSalaryExchange()) {
overlayLiveSalaryExchange(rows, condition);
@ -90,6 +95,8 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
(row, amount) -> row.setGiftConsume(add(row.getGiftConsume(), amount)));
mergeMongo(rows, condition, listLuckyGiftAnchorShare(condition),
(row, amount) -> row.setLuckyGiftAnchorShare(add(row.getLuckyGiftAnchorShare(), amount)));
mergeMongo(rows, condition, listBankSalaryTransfer(condition),
(row, amount) -> row.setSalaryTransfer(add(row.getSalaryTransfer(), amount)));
mergeDailyActive(rows, condition, listDailyActive(condition));
mergeRetention(rows, condition);
@ -165,20 +172,31 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
private void overlayLiveSalaryExchange(Map<String, CountryDashboardMetricCO> rows,
QueryCondition condition) {
rows.values().forEach(row -> row.setSalaryExchange(BigDecimal.ZERO));
List<CountryDashboardMetricDTO> metrics = countryDashboardDAO.listSalaryExchange(
mergeSqlSalaryExchange(rows, countryDashboardDAO.listSalaryExchange(
condition.periodType, condition.startTime, condition.endTime,
condition.countryKeyword, condition.sysOrigin,
condition.storageTimezoneOffset, condition.statTimezoneOffset);
condition.storageTimezoneOffset, condition.statTimezoneOffset));
mergeBankSalaryExchange(rows, condition);
}
private void mergeSqlSalaryExchange(Map<String, CountryDashboardMetricCO> rows,
List<CountryDashboardMetricDTO> metrics) {
if (metrics == null || metrics.isEmpty()) {
return;
}
for (CountryDashboardMetricDTO metric : metrics) {
CountryDashboardMetricCO row = getRow(rows, metric.getCountryCode(), metric.getCountryName(),
metric.getPeriodKey(), metric.getPeriodName());
row.setSalaryExchange(safe(metric.getSalaryExchange()));
row.setSalaryExchange(add(row.getSalaryExchange(), metric.getSalaryExchange()));
}
}
private void mergeBankSalaryExchange(Map<String, CountryDashboardMetricCO> rows,
QueryCondition condition) {
mergeMongo(rows, condition, listBankSalaryExchange(condition),
(row, amount) -> row.setSalaryExchange(add(row.getSalaryExchange(), amount)));
}
private boolean shouldUsePrecomputedMetrics(QueryCondition condition) {
if (!hasText(condition.sysOrigin)) {
return false;
@ -452,6 +470,22 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
return aggregateGiftAmount(criteria, "$acceptUsers.targetAmount", true, condition.statTimezone);
}
private List<MongoMetric> listBankSalaryExchange(QueryCondition condition) {
List<Criteria> criteria = baseBankRunningWaterCriteria(condition);
criteria.add(Criteria.where("event").is(BANK_EXCHANGE_GOLD_EVENT));
criteria.add(Criteria.where("type").is(RECEIPT_TYPE_EXPENDITURE));
return aggregateMongoAmount(criteria, "$amount", false, condition.statTimezone,
COLLECTION_USER_BANK_RUNNING_WATER);
}
private List<MongoMetric> listBankSalaryTransfer(QueryCondition condition) {
List<Criteria> criteria = baseBankRunningWaterCriteria(condition);
criteria.add(Criteria.where("event").is(BANK_TRANSFER_GOLD_EVENT));
criteria.add(Criteria.where("type").is(RECEIPT_TYPE_EXPENDITURE));
return aggregateMongoAmount(criteria, "$amount", false, condition.statTimezone,
COLLECTION_USER_BANK_RUNNING_WATER);
}
private List<MongoUserDayMetric> listDailyActive(QueryCondition condition) {
List<Criteria> criteria = baseActiveCriteria(condition);
List<AggregationOperation> operations = new ArrayList<>();
@ -506,18 +540,39 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
return criteria;
}
private List<Criteria> baseBankRunningWaterCriteria(QueryCondition condition) {
List<Criteria> criteria = new ArrayList<>();
criteria.add(Criteria.where("userId").ne(null));
if (condition.startInstant != null) {
criteria.add(Criteria.where("createTime").gte(Timestamp.from(condition.startInstant)));
}
if (condition.endInstant != null) {
criteria.add(Criteria.where("createTime").lt(Timestamp.from(condition.endInstant)));
}
if (hasText(condition.sysOrigin)) {
criteria.add(Criteria.where("sysOrigin").is(condition.sysOrigin));
}
return criteria;
}
private List<MongoMetric> aggregateGiftAmount(List<Criteria> criteria, String amountPath,
boolean unwindAcceptUsers, String statTimezone) {
return aggregateMongoAmount(criteria, amountPath, unwindAcceptUsers, statTimezone,
COLLECTION_GIFT_GIVE_RUNNING_WATER);
}
private List<MongoMetric> aggregateMongoAmount(List<Criteria> criteria, String amountPath,
boolean unwindAcceptUsers, String statTimezone, String collectionName) {
List<AggregationOperation> operations = new ArrayList<>();
operations.add(Aggregation.match(new Criteria().andOperator(criteria.toArray(new Criteria[0]))));
if (unwindAcceptUsers) {
operations.add(Aggregation.unwind("acceptUsers"));
}
operations.add(projectGiftDayAmount(amountPath, statTimezone));
operations.add(projectMongoDayAmount(amountPath, statTimezone));
operations.add(Aggregation.group("userId", "day").sum("amount").as("amount"));
return mongoTemplate.aggregate(Aggregation.newAggregation(operations),
COLLECTION_GIFT_GIVE_RUNNING_WATER, Document.class)
collectionName, Document.class)
.getMappedResults()
.stream()
.map(this::toMongoMetric)
@ -525,7 +580,7 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
.toList();
}
private AggregationOperation projectGiftDayAmount(String amountPath, String statTimezone) {
private AggregationOperation projectMongoDayAmount(String amountPath, String statTimezone) {
return context -> new Document("$project",
new Document("userId", "$userId")
.append("amount", amountPath)
@ -698,6 +753,7 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
total.setGoogleRecharge(add(total.getGoogleRecharge(), row.getGoogleRecharge()));
total.setDealerRecharge(add(total.getDealerRecharge(), row.getDealerRecharge()));
total.setSalaryExchange(add(total.getSalaryExchange(), row.getSalaryExchange()));
total.setSalaryTransfer(add(total.getSalaryTransfer(), row.getSalaryTransfer()));
total.setGiftConsume(add(total.getGiftConsume(), row.getGiftConsume()));
total.setLuckyGiftTotalFlow(add(total.getLuckyGiftTotalFlow(), row.getLuckyGiftTotalFlow()));
total.setLuckyGiftUser(total.getLuckyGiftUser() + safeLong(row.getLuckyGiftUser()));
@ -916,10 +972,6 @@ public class CountryDashboardServiceImpl implements CountryDashboardService {
if (PERIOD_ALL.equals(periodType) || startDateValue == null || endDateValue == null) {
return false;
}
LocalDate today = LocalDate.now(statZoneId);
if (endDateValue.isBefore(today) || startDateValue.isAfter(today)) {
return false;
}
long days = ChronoUnit.DAYS.between(startDateValue, endDateValue.plusDays(1));
return days <= 31;
}

View File

@ -38,6 +38,8 @@ public class CountryDashboardMetricCO implements Serializable {
private BigDecimal salaryExchange = BigDecimal.ZERO;
private BigDecimal salaryTransfer = BigDecimal.ZERO;
private BigDecimal totalRecharge = BigDecimal.ZERO;
private BigDecimal giftConsume = BigDecimal.ZERO;