客户画像代码开发

This commit is contained in:
spllzh
2025-09-21 21:34:59 +08:00
parent 004ba02996
commit f3eab70d43
5 changed files with 8 additions and 7 deletions

View File

@@ -1,384 +0,0 @@
package com.rj.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.entity.CpaBrandScoreStatistics;
import com.rj.mapper.CpaBrandScoreStatisticsMapper;
import com.rj.service.ICpaBrandScoreStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 经销商品牌得分统计表 服务实现类
*
* @author 李中华
* @date 2025/1/15
*/
@Slf4j
@Service
public class CpaBrandScoreStatisticsServiceImpl extends ServiceImpl<CpaBrandScoreStatisticsMapper, CpaBrandScoreStatistics>
implements ICpaBrandScoreStatisticsService {
@Autowired
private CpaBrandScoreStatisticsMapper cpaBrandScoreStatisticsMapper;
@Override
public List<CpaBrandScoreStatistics> getByDealerCodeAndType(String dealerCode, String statisticsType) {
return cpaBrandScoreStatisticsMapper.selectByDealerCodeAndType(dealerCode, statisticsType);
}
@Override
public List<CpaBrandScoreStatistics> getByBigAreaAndType(String bigArea, String statisticsType) {
return cpaBrandScoreStatisticsMapper.selectByBigAreaAndType(bigArea, statisticsType);
}
@Override
public List<CpaBrandScoreStatistics> getByDateRange(LocalDate startDate, LocalDate endDate, String statisticsType) {
return cpaBrandScoreStatisticsMapper.selectByDateRange(startDate, endDate, statisticsType);
}
@Override
public List<Map<String, Object>> getDealerRanking(String statisticsType, Integer limit) {
return cpaBrandScoreStatisticsMapper.selectDealerRanking(statisticsType, limit);
}
@Override
public List<Map<String, Object>> getBigAreaRanking(String statisticsType) {
return cpaBrandScoreStatisticsMapper.selectBigAreaRanking(statisticsType);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean batchSave(List<CpaBrandScoreStatistics> statisticsList) {
try {
if (statisticsList == null || statisticsList.isEmpty()) {
log.warn("批量保存统计数据为空");
return false;
}
// 设置创建时间
LocalDateTime now = LocalDateTime.now();
statisticsList.forEach(statistics -> {
if (statistics.getCreatedAt() == null) {
statistics.setCreatedAt(now);
}
if (statistics.getUpdatedAt() == null) {
statistics.setUpdatedAt(now);
}
if (statistics.getIsDeleted() == null) {
statistics.setIsDeleted(0);
}
});
int result = cpaBrandScoreStatisticsMapper.batchInsert(statisticsList);
log.info("批量保存统计数据成功,保存记录数:{}", result);
return result > 0;
} catch (Exception e) {
log.error("批量保存统计数据失败", e);
throw e;
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteByCondition(String dealerCode, String statisticsType, LocalDate startDate, LocalDate endDate) {
try {
int result = cpaBrandScoreStatisticsMapper.deleteByCondition(dealerCode, statisticsType, startDate, endDate);
log.info("根据条件删除统计数据成功,删除记录数:{}", result);
return result >= 0;
} catch (Exception e) {
log.error("根据条件删除统计数据失败", e);
throw e;
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public int generateAndSaveStatistics(String statisticsType, LocalDate startDate, LocalDate endDate, String createdBy) {
try {
log.info("开始生成统计数据,统计类型:{},日期范围:{} - {}", statisticsType, startDate, endDate);
List<Map<String, Object>> statisticsResults;
// 根据统计类型执行不同的统计SQL
if ("daily".equals(statisticsType)) {
// 日统计:使用传入的日期,按经销商和日期双重分组
if (startDate == null) {
throw new IllegalArgumentException("日统计需要提供统计日期");
}
// 先删除已存在的统计数据
deleteByCondition(null, statisticsType, startDate, startDate);
String startDateTime = startDate.atStartOfDay().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String endDateTime = startDate.atTime(23, 59, 59).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
statisticsResults = cpaBrandScoreStatisticsMapper.executeDailyStatistics(startDateTime, endDateTime);
} else if ("weekly".equals(statisticsType)) {
// 周统计:自动计算上周的开始和结束时间
LocalDate lastWeekStart = LocalDate.now().minusWeeks(1).with(java.time.DayOfWeek.MONDAY);
LocalDate lastWeekEnd = lastWeekStart.plusDays(6);
log.info("周统计自动计算时间范围:{} - {}", lastWeekStart, lastWeekEnd);
// 先删除已存在的统计数据
deleteByCondition(null, statisticsType, lastWeekStart, lastWeekEnd);
String startDateTime = lastWeekStart.atStartOfDay().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String endDateTime = lastWeekEnd.atTime(23, 59, 59).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
statisticsResults = cpaBrandScoreStatisticsMapper.executeDateRangeStatistics(startDateTime, endDateTime);
} else if ("monthly".equals(statisticsType)) {
// 月统计:自动计算上个月的开始和结束时间
LocalDate lastMonthStart = LocalDate.now().minusMonths(1).withDayOfMonth(1);
LocalDate lastMonthEnd = lastMonthStart.withDayOfMonth(lastMonthStart.lengthOfMonth());
log.info("月统计自动计算时间范围:{} - {}", lastMonthStart, lastMonthEnd);
// 先删除已存在的统计数据
deleteByCondition(null, statisticsType, lastMonthStart, lastMonthEnd);
String startDateTime = lastMonthStart.atStartOfDay().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
String endDateTime = lastMonthEnd.atTime(23, 59, 59).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
statisticsResults = cpaBrandScoreStatisticsMapper.executeDateRangeStatistics(startDateTime, endDateTime);
} else if ("total".equals(statisticsType)) {
// 总计统计:统计所有历史数据
// 先删除已存在的统计数据
deleteByCondition(null, statisticsType, null, null);
statisticsResults = cpaBrandScoreStatisticsMapper.executeTotalStatistics();
} else {
throw new IllegalArgumentException("不支持的统计类型:" + statisticsType);
}
// 转换为实体对象并保存
LocalDate statisticsDate;
if ("weekly".equals(statisticsType)) {
// 周统计使用上周的结束日期作为统计日期
statisticsDate = LocalDate.now().minusWeeks(1).with(java.time.DayOfWeek.MONDAY).plusDays(6);
} else if ("monthly".equals(statisticsType)) {
// 月统计使用上月的最后一天作为统计日期
statisticsDate = LocalDate.now().minusMonths(1).withDayOfMonth(1).withDayOfMonth(
LocalDate.now().minusMonths(1).withDayOfMonth(1).lengthOfMonth());
} else {
// 日统计和总计统计使用传入的日期
statisticsDate = endDate;
}
List<CpaBrandScoreStatistics> statisticsList = convertToStatisticsList(statisticsResults, statisticsDate, statisticsType, createdBy);
boolean success = batchSave(statisticsList);
if (success) {
log.info("统计数据生成完成,统计类型:{},统计日期:{},生成记录数:{}", statisticsType, statisticsDate, statisticsList.size());
return statisticsList.size();
} else {
log.error("统计数据保存失败,统计类型:{}", statisticsType);
return 0;
}
} catch (Exception e) {
log.error("生成统计数据失败", e);
throw e;
}
}
@Override
public Map<String, Object> getStatisticsOverview(String statisticsType, LocalDate startDate, LocalDate endDate) {
Map<String, Object> overview = new HashMap<>();
try {
// 获取统计数据列表
List<CpaBrandScoreStatistics> statisticsList = getByDateRange(startDate, endDate, statisticsType);
if (statisticsList.isEmpty()) {
overview.put("totalDealers", 0);
overview.put("totalRecords", 0);
overview.put("averageScore", 0.0);
overview.put("topDealer", null);
return overview;
}
// 计算概览数据
int totalDealers = (int) statisticsList.stream()
.map(CpaBrandScoreStatistics::getDealerCode)
.distinct()
.count();
int totalRecords = statisticsList.stream()
.mapToInt(CpaBrandScoreStatistics::getTotalRecords)
.sum();
double averageScore = statisticsList.stream()
.mapToDouble(s -> s.getAverageScorePercentage().doubleValue())
.average()
.orElse(0.0);
// 获取得分最高的经销商
CpaBrandScoreStatistics topDealer = statisticsList.stream()
.max((s1, s2) -> s1.getAverageScorePercentage().compareTo(s2.getAverageScorePercentage()))
.orElse(null);
overview.put("totalDealers", totalDealers);
overview.put("totalRecords", totalRecords);
overview.put("averageScore", averageScore);
overview.put("topDealer", topDealer);
overview.put("statisticsCount", statisticsList.size());
log.info("获取统计概览数据成功,经销商数:{},总记录数:{},平均得分:{}",
totalDealers, totalRecords, averageScore);
} catch (Exception e) {
log.error("获取统计概览数据失败", e);
throw e;
}
return overview;
}
/**
* 根据条件查询统计数据(支持分页)
*
* @param dealerCode 经销商编码
* @param bigArea 大区
* @param statisticsType 统计类型
* @param startDate 开始日期
* @param endDate 结束日期
* @return 统计数据列表
*/
public List<CpaBrandScoreStatistics> getByCondition(String dealerCode, String bigArea,
String statisticsType, LocalDate startDate, LocalDate endDate) {
LambdaQueryWrapper<CpaBrandScoreStatistics> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CpaBrandScoreStatistics::getIsDeleted, 0);
if (dealerCode != null && !dealerCode.trim().isEmpty()) {
queryWrapper.eq(CpaBrandScoreStatistics::getDealerCode, dealerCode);
}
if (bigArea != null && !bigArea.trim().isEmpty()) {
queryWrapper.eq(CpaBrandScoreStatistics::getBigArea, bigArea);
}
if (statisticsType != null && !statisticsType.trim().isEmpty()) {
queryWrapper.eq(CpaBrandScoreStatistics::getStatisticsType, statisticsType);
}
if (startDate != null) {
queryWrapper.ge(CpaBrandScoreStatistics::getStatisticsDate, startDate);
}
if (endDate != null) {
queryWrapper.le(CpaBrandScoreStatistics::getStatisticsDate, endDate);
}
queryWrapper.orderByDesc(CpaBrandScoreStatistics::getAverageScorePercentage)
.orderByDesc(CpaBrandScoreStatistics::getTotalScore);
return list(queryWrapper);
}
/**
* 将查询结果转换为统计实体列表
*
* @param results 查询结果
* @param statisticsDate 统计日期
* @param statisticsType 统计类型
* @param createdBy 创建人
* @return 统计实体列表
*/
private List<CpaBrandScoreStatistics> convertToStatisticsList(List<Map<String, Object>> results,
LocalDate statisticsDate,
String statisticsType,
String createdBy) {
List<CpaBrandScoreStatistics> statisticsList = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
for (Map<String, Object> row : results) {
CpaBrandScoreStatistics statistics = new CpaBrandScoreStatistics();
statistics.setId(java.util.UUID.randomUUID().toString());
statistics.setDealerCode((String) row.get("dealer_code"));
statistics.setDealerName((String) row.get("dealer_name"));
statistics.setBigArea((String) row.get("big_area"));
// 对于日统计,使用查询结果中的日期;其他统计类型使用传入的日期
if ("daily".equals(statisticsType) && row.get("statistics_date") != null) {
if (row.get("statistics_date") instanceof java.sql.Date) {
statistics.setStatisticsDate(((java.sql.Date) row.get("statistics_date")).toLocalDate());
} else {
statistics.setStatisticsDate(statisticsDate);
}
} else {
statistics.setStatisticsDate(statisticsDate);
}
statistics.setStatisticsType(statisticsType);
// 数值字段转换
statistics.setTotalRecords(convertToInteger(row.get("daily_records")));
statistics.setTotalScore(convertToInteger(row.get("daily_total_score")));
statistics.setAverageScorePercentage(convertToBigDecimal(row.get("daily_average_score_percentage")));
statistics.setPositiveCount(convertToInteger(row.get("daily_positive_count")));
statistics.setNeutralCount(convertToInteger(row.get("daily_neutral_count")));
statistics.setNegativeCount(convertToInteger(row.get("daily_negative_count")));
statistics.setPositiveRate(convertToBigDecimal(row.get("daily_positive_rate")));
statistics.setNeutralRate(convertToBigDecimal(row.get("daily_neutral_rate")));
statistics.setNegativeRate(convertToBigDecimal(row.get("daily_negative_rate")));
// 时间字段转换
statistics.setEarliestInteraction(convertToLocalDateTime(row.get("daily_earliest_time")));
statistics.setLatestInteraction(convertToLocalDateTime(row.get("daily_latest_time")));
// 系统字段
statistics.setCreatedAt(now);
statistics.setUpdatedAt(now);
statistics.setCreatedBy(createdBy != null ? createdBy : "system");
statistics.setUpdatedBy(createdBy != null ? createdBy : "system");
statistics.setIsDeleted(0);
statisticsList.add(statistics);
}
return statisticsList;
}
/**
* 类型转换辅助方法
*/
private Integer convertToInteger(Object value) {
if (value == null) return 0;
if (value instanceof Number) {
return ((Number) value).intValue();
}
return Integer.parseInt(value.toString());
}
private java.math.BigDecimal convertToBigDecimal(Object value) {
if (value == null) return java.math.BigDecimal.ZERO;
if (value instanceof Number) {
return java.math.BigDecimal.valueOf(((Number) value).doubleValue());
}
return new java.math.BigDecimal(value.toString());
}
private LocalDateTime convertToLocalDateTime(Object value) {
if (value == null) return null;
if (value instanceof java.sql.Timestamp) {
return ((java.sql.Timestamp) value).toLocalDateTime();
}
if (value instanceof java.sql.Date) {
return ((java.sql.Date) value).toLocalDate().atStartOfDay();
}
return LocalDateTime.parse(value.toString());
}
}