package com.talentcard.server.service; import com.talentcard.server.common.BusinessException; import com.talentcard.server.common.ErrorCode; import com.talentcard.server.mapper.AdminWorkbenchStatisticsMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @Service public class AdminWorkbenchStatisticsService { private final AdminWorkbenchStatisticsMapper mapper; public AdminWorkbenchStatisticsService(AdminWorkbenchStatisticsMapper mapper) { this.mapper = mapper; } @Transactional(readOnly = true) public Map summary(String period) { Map row = mapper.selectSummary(); Map compareRow = mapper.selectCompareSummary(); if (row == null || compareRow == null) { throw new BusinessException(ErrorCode.INTERNAL_ERROR, "工作台统计查询失败"); } long subsidyCents = number(row.get("subsidyAmountCents")); long monthlyVerification = number(row.get("monthlyVerificationCount")); long talentCount = number(row.get("talentCount")); Map result = new LinkedHashMap<>(); result.put("totalSubsidyAmountCents", subsidyCents); result.put("totalSubsidyAmount", money(subsidyCents)); result.put("cumulativeSubsidyTotal", money(subsidyCents)); result.put("monthlyVerificationCount", monthlyVerification); result.put("monthlyVerificationOrders", monthlyVerification); result.put("talentCount", talentCount); result.put("cardholderTotal", talentCount); result.put("talentCompare", number(compareRow.get("talentCompare"))); result.put("monthlyVerificationCompare", number(compareRow.get("monthlyVerificationCompare"))); result.put("subsidyCompare", money(number(compareRow.get("subsidyCompareCents")))); List> summaryTrend = mapper.selectSummaryTrend(); result.put("talentSpark", trendValues(summaryTrend, "talent")); result.put("verificationSpark", trendValues(summaryTrend, "verification")); result.put("subsidySpark", trendValues(summaryTrend, "subsidy")); result.put("budgetConfigured", false); result.put("budgetUsageRate", BigDecimal.ZERO.setScale(2)); result.put("budgetUsageRateText", "0.00%"); List> alerts = new ArrayList<>(); addAlert(alerts, "待处理订单", number(row.get("pendingOrderCount"))); addAlert(alerts, "待审核商家", number(row.get("pendingProductCount"))); addAlert(alerts, "待处理申请", number(row.get("pendingApplicationCount"))); result.put("alertCount", alerts.stream().mapToLong(a -> number(a.get("count"))).sum()); result.put("alerts", alerts); result.put("statisticsBasis", "补贴仅统计政府承担的商品补贴和政府补贴券金额,商家自行让利不计入政府补贴"); result.put("verificationTrend", verificationTrend(period)); result.put("verificationPeriod", normalizePeriod(period)); result.put("pendingItems", mapper.selectPendingItems()); List> hotMerchants = mapper.selectHotMerchants(); for (int index = 0; index < hotMerchants.size(); index++) { hotMerchants.get(index).put("rank", index + 1); } result.put("hotMerchants", hotMerchants); result.put("orderCategoryShares", mapper.selectOrderCategoryShares()); return result; } private List> verificationTrend(String period) { return switch (normalizePeriod(period)) { case "week" -> mapper.selectWeeklyVerificationTrend(); case "year" -> mapper.selectYearlyVerificationTrend(); default -> mapper.selectMonthlyVerificationTrend(); }; } private String normalizePeriod(String period) { if (period == null || period.isBlank()) { return "month"; } String normalized = period.trim().toLowerCase(); return switch (normalized) { case "week", "month", "year" -> normalized; default -> "month"; }; } private void addAlert(List> alerts, String type, long count) { if (count <= 0) return; Map alert = new LinkedHashMap<>(); alert.put("type", type); alert.put("count", count); alerts.add(alert); } private List trendValues(List> rows, String key) { if (rows == null) { return List.of(); } return rows.stream() .map(row -> decimal(row.get(key))) .toList(); } private BigDecimal decimal(Object value) { if (value instanceof BigDecimal decimal) { return decimal; } if (value instanceof Number number) { return BigDecimal.valueOf(number.doubleValue()); } return BigDecimal.ZERO; } private long number(Object value) { return value instanceof Number n ? n.longValue() : 0L; } private BigDecimal money(long cents) { return BigDecimal.valueOf(cents, 2).setScale(2, RoundingMode.HALF_UP); } }