.
This commit is contained in:
@@ -2054,6 +2054,264 @@ public class MarketingAnalysisService {
|
||||
return chartsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует сырые данные графиков в формат Chart.js (labels, datasets).
|
||||
*
|
||||
* @param rawData сырые данные из parseChartDataFromJson
|
||||
* @return Map с данными в формате Chart.js для графиков и исходными данными для
|
||||
* таблиц
|
||||
*/
|
||||
private Map<String, Object> transformToChartConfig(Map<String, Object> rawData) {
|
||||
logger.info("transformToChartConfig: Starting transformation to Chart.js format");
|
||||
Map<String, Object> formattedCharts = new HashMap<>();
|
||||
|
||||
if (rawData == null || rawData.isEmpty()) {
|
||||
logger.warn("transformToChartConfig: rawData is null or empty");
|
||||
return formattedCharts;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. Seasonality (Map<String, Integer>)
|
||||
if (rawData.containsKey("seasonality")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Integer> seasonality = (Map<String, Integer>) rawData.get("seasonality");
|
||||
if (seasonality != null && !seasonality.isEmpty()) {
|
||||
List<String> labels = new ArrayList<>(seasonality.keySet());
|
||||
List<Integer> data = new ArrayList<>(seasonality.values());
|
||||
|
||||
Map<String, Object> dataset = new HashMap<>();
|
||||
dataset.put("label", "Индекс спроса");
|
||||
dataset.put("data", data);
|
||||
|
||||
Map<String, Object> chart = new HashMap<>();
|
||||
chart.put("labels", labels);
|
||||
chart.put("datasets", List.of(dataset));
|
||||
formattedCharts.put("seasonality", chart);
|
||||
|
||||
logger.debug("transformToChartConfig: Transformed seasonality chart with {} labels", labels.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Competitors (List<Map>)
|
||||
if (rawData.containsKey("competitors")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> competitors = (List<Map<String, Object>>) rawData.get("competitors");
|
||||
if (competitors != null && !competitors.isEmpty()) {
|
||||
List<String> labels = new ArrayList<>();
|
||||
List<Integer> data = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> competitor : competitors) {
|
||||
labels.add((String) competitor.getOrDefault("name", "Unknown"));
|
||||
|
||||
// Безопасное извлечение digitalMetrics.reach
|
||||
Object metricsObj = competitor.get("digitalMetrics");
|
||||
if (metricsObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> digitalMetrics = (Map<String, Object>) metricsObj;
|
||||
Object reachObj = digitalMetrics.get("reach");
|
||||
if (reachObj instanceof Number) {
|
||||
data.add(((Number) reachObj).intValue());
|
||||
} else {
|
||||
data.add(0);
|
||||
}
|
||||
} else {
|
||||
data.add(0);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> dataset = new HashMap<>();
|
||||
dataset.put("label", "Охват аудитории");
|
||||
dataset.put("data", data);
|
||||
|
||||
Map<String, Object> chart = new HashMap<>();
|
||||
chart.put("labels", labels);
|
||||
chart.put("datasets", List.of(dataset));
|
||||
formattedCharts.put("competitors", chart);
|
||||
|
||||
// Сохраняем исходные данные конкурентов для таблиц
|
||||
formattedCharts.put("competitorsRaw", competitors);
|
||||
|
||||
logger.debug("transformToChartConfig: Transformed competitors chart with {} entries",
|
||||
labels.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Audience Segmentation (Map с ageGroups и genders)
|
||||
if (rawData.containsKey("audienceSegmentation")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> segmentation = (Map<String, Object>) rawData.get("audienceSegmentation");
|
||||
if (segmentation != null) {
|
||||
// 3.1. Audience Age Chart
|
||||
if (segmentation.containsKey("ageGroups")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, String>> ageGroups = (List<Map<String, String>>) segmentation.get("ageGroups");
|
||||
if (ageGroups != null && !ageGroups.isEmpty()) {
|
||||
List<String> labels = new ArrayList<>();
|
||||
List<Number> data = new ArrayList<>();
|
||||
|
||||
for (Map<String, String> ageGroup : ageGroups) {
|
||||
labels.add(ageGroup.getOrDefault("label", "Unknown"));
|
||||
String valueStr = ageGroup.getOrDefault("value", "0");
|
||||
try {
|
||||
data.add(Integer.parseInt(valueStr));
|
||||
} catch (NumberFormatException e) {
|
||||
data.add(0);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> dataset = new HashMap<>();
|
||||
dataset.put("label", "Возрастные группы");
|
||||
dataset.put("data", data);
|
||||
|
||||
Map<String, Object> chart = new HashMap<>();
|
||||
chart.put("labels", labels);
|
||||
chart.put("datasets", List.of(dataset));
|
||||
formattedCharts.put("audienceAge", chart);
|
||||
|
||||
logger.debug("transformToChartConfig: Transformed audienceAge chart with {} labels",
|
||||
labels.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 3.2. Audience Gender Chart
|
||||
if (segmentation.containsKey("genders")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, String>> genders = (List<Map<String, String>>) segmentation.get("genders");
|
||||
if (genders != null && !genders.isEmpty()) {
|
||||
List<String> labels = new ArrayList<>();
|
||||
List<Number> data = new ArrayList<>();
|
||||
|
||||
for (Map<String, String> gender : genders) {
|
||||
labels.add(gender.getOrDefault("label", "Unknown"));
|
||||
String valueStr = gender.getOrDefault("value", "0");
|
||||
try {
|
||||
data.add(Integer.parseInt(valueStr));
|
||||
} catch (NumberFormatException e) {
|
||||
data.add(0);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> dataset = new HashMap<>();
|
||||
dataset.put("label", "Гендерное распределение");
|
||||
dataset.put("data", data);
|
||||
|
||||
Map<String, Object> chart = new HashMap<>();
|
||||
chart.put("labels", labels);
|
||||
chart.put("datasets", List.of(dataset));
|
||||
formattedCharts.put("audienceGender", chart);
|
||||
|
||||
logger.debug("transformToChartConfig: Transformed audienceGender chart with {} labels",
|
||||
labels.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Сохраняем остальные данные из audienceSegmentation как есть
|
||||
if (segmentation.containsKey("segments")) {
|
||||
formattedCharts.put("segments", segmentation.get("segments"));
|
||||
}
|
||||
if (segmentation.containsKey("segmentsChannelMatrix")) {
|
||||
formattedCharts.put("segmentsChannelMatrix", segmentation.get("segmentsChannelMatrix"));
|
||||
}
|
||||
if (segmentation.containsKey("keyTakeaways")) {
|
||||
formattedCharts.put("keyTakeaways", segmentation.get("keyTakeaways"));
|
||||
}
|
||||
|
||||
// Сохраняем исходную структуру audienceSegmentation для обратной совместимости
|
||||
formattedCharts.put("audienceSegmentation", segmentation);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Conversion Funnel (List<Map>)
|
||||
if (rawData.containsKey("conversionFunnel")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> funnel = (List<Map<String, Object>>) rawData.get("conversionFunnel");
|
||||
if (funnel != null && !funnel.isEmpty()) {
|
||||
List<String> labels = new ArrayList<>();
|
||||
List<Number> data = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> stage : funnel) {
|
||||
labels.add((String) stage.getOrDefault("stage", "Unknown"));
|
||||
Object valueObj = stage.get("value");
|
||||
if (valueObj instanceof Number) {
|
||||
data.add(((Number) valueObj).intValue());
|
||||
} else {
|
||||
data.add(0);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> dataset = new HashMap<>();
|
||||
dataset.put("label", "Воронка");
|
||||
dataset.put("data", data);
|
||||
|
||||
Map<String, Object> chart = new HashMap<>();
|
||||
chart.put("labels", labels);
|
||||
chart.put("datasets", List.of(dataset));
|
||||
formattedCharts.put("conversionFunnel", chart);
|
||||
|
||||
logger.debug("transformToChartConfig: Transformed conversionFunnel chart with {} stages",
|
||||
labels.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Channels Potential (List<Map>)
|
||||
if (rawData.containsKey("channelsPotential")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> channels = (List<Map<String, Object>>) rawData.get("channelsPotential");
|
||||
if (channels != null && !channels.isEmpty()) {
|
||||
List<String> labels = new ArrayList<>();
|
||||
List<Number> data = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> channel : channels) {
|
||||
labels.add((String) channel.getOrDefault("name", "Unknown"));
|
||||
Object potentialObj = channel.get("potential");
|
||||
if (potentialObj instanceof Number) {
|
||||
data.add(((Number) potentialObj).intValue());
|
||||
} else {
|
||||
data.add(0);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> dataset = new HashMap<>();
|
||||
dataset.put("label", "Потенциал");
|
||||
dataset.put("data", data);
|
||||
|
||||
Map<String, Object> chart = new HashMap<>();
|
||||
chart.put("labels", labels);
|
||||
chart.put("datasets", List.of(dataset));
|
||||
formattedCharts.put("channelsPotential", chart);
|
||||
|
||||
logger.debug("transformToChartConfig: Transformed channelsPotential chart with {} channels",
|
||||
labels.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Данные без преобразования (оставить как есть)
|
||||
if (rawData.containsKey("swot")) {
|
||||
formattedCharts.put("swot", rawData.get("swot"));
|
||||
}
|
||||
if (rawData.containsKey("comparisonTable")) {
|
||||
formattedCharts.put("comparisonTable", rawData.get("comparisonTable"));
|
||||
}
|
||||
if (rawData.containsKey("marketShareChart")) {
|
||||
formattedCharts.put("marketShareChart", rawData.get("marketShareChart"));
|
||||
}
|
||||
if (rawData.containsKey("swotCompetitors")) {
|
||||
formattedCharts.put("swotCompetitors", rawData.get("swotCompetitors"));
|
||||
}
|
||||
if (rawData.containsKey("market")) {
|
||||
formattedCharts.put("market", rawData.get("market"));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("transformToChartConfig: Error transforming chart data: {}", e.getMessage(), e);
|
||||
logger.error("transformToChartConfig: Stack trace: ", e);
|
||||
}
|
||||
|
||||
logger.info("transformToChartConfig: Transformation completed. Formatted charts keys: {}",
|
||||
formattedCharts.keySet());
|
||||
return formattedCharts;
|
||||
}
|
||||
|
||||
private Map<String, Object> generateMarketingReport(MarketingAnalysisRequest request) {
|
||||
logger.info("generateMarketingReport: Starting report generation for product: {}", request.getProduct());
|
||||
Map<String, Object> report = new HashMap<>();
|
||||
@@ -2152,13 +2410,18 @@ public class MarketingAnalysisService {
|
||||
Map<String, Object> chartsData = parseChartDataFromJson(analysisJson);
|
||||
logger.info("generateMarketingReport: Chart data parsed. Keys: {}",
|
||||
chartsData != null ? chartsData.keySet() : "null");
|
||||
report.put("chartsData", chartsData);
|
||||
|
||||
// Преобразуем данные в формат Chart.js
|
||||
Map<String, Object> readyToRenderCharts = transformToChartConfig(chartsData);
|
||||
logger.info("generateMarketingReport: Chart data transformed to Chart.js format. Keys: {}",
|
||||
readyToRenderCharts != null ? readyToRenderCharts.keySet() : "null");
|
||||
report.put("chartsData", readyToRenderCharts);
|
||||
|
||||
// Заменяем плейсхолдеры графиков на JSON-блоки
|
||||
String processedTextReport = textReport;
|
||||
if (textReport != null && chartsData != null && !chartsData.isEmpty()) {
|
||||
if (textReport != null && readyToRenderCharts != null && !readyToRenderCharts.isEmpty()) {
|
||||
logger.info("generateMarketingReport: Replacing chart placeholders in text report");
|
||||
processedTextReport = replaceChartPlaceholders(textReport, chartsData);
|
||||
processedTextReport = replaceChartPlaceholders(textReport, readyToRenderCharts);
|
||||
logger.info("generateMarketingReport: Chart placeholders replaced. Length: {} chars",
|
||||
processedTextReport != null ? processedTextReport.length() : 0);
|
||||
} else if (textReport != null) {
|
||||
|
||||
Reference in New Issue
Block a user