all types of analyses

This commit is contained in:
root
2025-12-06 20:20:12 +05:00
parent 021e6e7c60
commit beee7d71a2
2 changed files with 139 additions and 90 deletions
@@ -85,45 +85,29 @@ public class MarketingController {
return unauthorizedResponse();
}
// Create analysis records (one for each analysis type)
// Create unified analysis with all analysis types
List<MarketingAnalysis> analyses = marketingAnalysisService.startAnalysis(request, userId);
MarketingAnalysis analysis = analyses.get(0);
// Start async processing for each analysis
for (MarketingAnalysis analysis : analyses) {
marketingAnalysisService.processAnalysis(analysis.getId(), request);
}
// Start async processing
marketingAnalysisService.processAnalysis(analysis.getId(), request);
// Calculate estimated completion time (5-10 minutes)
LocalDateTime estimatedCompletion = LocalDateTime.now().plusMinutes(8);
// If multiple analyses, return list of responses
if (analyses.size() > 1) {
List<MarketingAnalysisResponse> responses = analyses.stream()
.map(analysis -> new MarketingAnalysisResponse(
analysis.getId(),
"processing",
estimatedCompletion,
"Анализ типа '" +
(analysis.getAnalysisType() != null && !analysis
.getAnalysisType().isEmpty()
? analysis.getAnalysisType()
.get(0)
: "неизвестно")
+
"' запущен успешно. Результаты будут готовы в течение 5-10 минут."))
.collect(Collectors.toList());
return ResponseEntity.ok(ApiResponse.success(
"Создано анализов: " + analyses.size() + ". Все анализы запущены успешно.",
responses));
} else {
MarketingAnalysis analysis = analyses.get(0);
MarketingAnalysisResponse response = new MarketingAnalysisResponse(
analysis.getId(),
"processing",
estimatedCompletion,
"Анализ запущен успешно. Результаты будут готовы в течение 5-10 минут.");
return ResponseEntity.ok(ApiResponse.success("Анализ запущен успешно", response));
// Build analysis types string for message
String analysisTypesStr = "неизвестно";
if (analysis.getAnalysisType() != null && !analysis.getAnalysisType().isEmpty()) {
analysisTypesStr = String.join(", ", analysis.getAnalysisType());
}
MarketingAnalysisResponse response = new MarketingAnalysisResponse(
analysis.getId(),
"processing",
estimatedCompletion,
"Комплексный анализ (" + analysisTypesStr
+ ") запущен успешно. Результаты будут готовы в течение 5-10 минут.");
return ResponseEntity.ok(ApiResponse.success("Анализ запущен успешно", response));
}
@GetMapping("/{analysisId}")
@@ -43,27 +43,26 @@ public class MarketingAnalysisService {
throw new IllegalArgumentException("Необходимо выбрать хотя бы один тип анализа");
}
List<MarketingAnalysis> analyses = new ArrayList<>();
for (String analysisType : analysisTypes) {
MarketingAnalysis analysis = new MarketingAnalysis(
request.getBusinessNiche(),
request.getProduct(),
request.getTargetAudience(),
request.getRegion(),
request.getGoal(),
request.getDetailLevel(),
request.getStrongSide(),
request.getWeakSide(),
List.of(analysisType)); // Каждый анализ имеет один тип
analysis.setUserId(userId);
analysis.setStatus("queued");
addStatusHistoryEntry(analysis, "queued", "Анализ создан и добавлен в очередь");
analysis = repository.save(analysis);
analyses.add(analysis);
logger.info("Marketing analysis created with ID: {} for user: {} with type: {}",
analysis.getId(), userId, analysisType);
}
return analyses;
// Create a single unified analysis with all analysis types
MarketingAnalysis analysis = new MarketingAnalysis(
request.getBusinessNiche(),
request.getProduct(),
request.getTargetAudience(),
request.getRegion(),
request.getGoal(),
request.getDetailLevel(),
request.getStrongSide(),
request.getWeakSide(),
analysisTypes); // Все типы анализа в одном анализе
analysis.setUserId(userId);
analysis.setStatus("queued");
addStatusHistoryEntry(analysis, "queued", "Комплексный анализ создан и добавлен в очередь");
analysis = repository.save(analysis);
logger.info("Unified marketing analysis created with ID: {} for user: {} with types: {}",
analysis.getId(), userId, analysisTypes);
return List.of(analysis);
}
private void addStatusHistoryEntry(MarketingAnalysis analysis, String status, String message) {
@@ -90,19 +89,15 @@ public class MarketingAnalysisService {
logger.info("Starting marketing analysis processing for ID: {}", analysisId);
// Create a modified request with single analysis type for this analysis
MarketingAnalysisRequest singleTypeRequest = createSingleTypeRequest(request,
analysis.getAnalysisType().get(0));
// Generate marketing report
Map<String, Object> reportData = generateMarketingReport(singleTypeRequest);
// Generate marketing report with all analysis types
Map<String, Object> reportData = generateMarketingReport(request);
// Generate markdown content for PDF
String markdownContent = buildMarkdownFromReport(reportData, singleTypeRequest);
String markdownContent = buildMarkdownFromReport(reportData, request);
// Generate PDF
byte[] pdfBytes = researchPdfService.generatePdfReport(
"Маркетинговый анализ: " + singleTypeRequest.getProduct(),
"Маркетинговый анализ: " + request.getProduct(),
markdownContent,
new ArrayList<>());
@@ -137,30 +132,21 @@ public class MarketingAnalysisService {
}
}
private MarketingAnalysisRequest createSingleTypeRequest(MarketingAnalysisRequest originalRequest,
String analysisType) {
MarketingAnalysisRequest singleTypeRequest = new MarketingAnalysisRequest();
singleTypeRequest.setBusinessNiche(originalRequest.getBusinessNiche());
singleTypeRequest.setProduct(originalRequest.getProduct());
singleTypeRequest.setTargetAudience(originalRequest.getTargetAudience());
singleTypeRequest.setRegion(originalRequest.getRegion());
singleTypeRequest.setGoal(originalRequest.getGoal());
singleTypeRequest.setDetailLevel(originalRequest.getDetailLevel());
singleTypeRequest.setStrongSide(originalRequest.getStrongSide());
singleTypeRequest.setWeakSide(originalRequest.getWeakSide());
singleTypeRequest.setAnalysisType(List.of(analysisType));
return singleTypeRequest;
}
private Map<String, Object> generateMarketingReport(MarketingAnalysisRequest request) {
Map<String, Object> report = new HashMap<>();
// Get analysis type and detail level - теперь всегда один тип
// Get all analysis types and detail level
List<AnalysisType> analysisTypes = request.getAnalysisTypeEnums();
AnalysisType analysisType = analysisTypes != null && !analysisTypes.isEmpty() ? analysisTypes.get(0) : null;
String analysisTypeName = analysisType != null ? analysisType.getDisplayName() : "Общий";
if (analysisTypes == null || analysisTypes.isEmpty()) {
analysisTypes = List.of(AnalysisType.РЫНОК); // Default
}
DetailLevel detailLevel = request.getDetailLevelEnum();
String detailLevelName = detailLevel != null ? detailLevel.getDisplayName() : "Стандартно";
// Build list of analysis type names for display
List<String> analysisTypeNames = analysisTypes.stream()
.map(AnalysisType::getDisplayName)
.toList();
// Build context for AI with all new fields
StringBuilder contextBuilder = new StringBuilder();
@@ -208,14 +194,16 @@ public class MarketingAnalysisService {
if (request.getWeakSide() != null && !request.getWeakSide().trim().isEmpty()) {
contextBuilder.append("Слабая сторона: ").append(request.getWeakSide()).append("\n");
}
contextBuilder.append("Тип анализа: ").append(analysisTypeName).append("\n");
contextBuilder.append("Типы анализа: ").append(String.join(", ", analysisTypeNames)).append("\n");
String context = contextBuilder.toString();
// Generate analysis based on type and detail level
String analysisContent = generateAnalysisByType(context, analysisType, detailLevel);
report.put("analysisType", analysisTypeName);
// Generate unified analysis with all types
String unifiedAnalysisContent = generateUnifiedAnalysis(context, analysisTypes, detailLevel);
// Store analysis data
report.put("analysisTypes", analysisTypeNames);
report.put("detailLevel", detailLevelName);
report.put("summary", analysisContent != null ? analysisContent : "Анализ не удалось сгенерировать.");
report.put("summary", unifiedAnalysisContent != null ? unifiedAnalysisContent : "Анализ не удалось сгенерировать.");
// Generate target audience description (adjusted by detail level)
String audiencePrompt;
@@ -302,6 +290,79 @@ public class MarketingAnalysisService {
return report;
}
private String generateUnifiedAnalysis(String context, List<AnalysisType> analysisTypes, DetailLevel detailLevel) {
if (analysisTypes == null || analysisTypes.isEmpty()) {
analysisTypes = List.of(AnalysisType.РЫНОК); // Default
}
if (detailLevel == null) {
detailLevel = DetailLevel.СТАНДАРТНО; // Default
}
String lengthInstruction;
// Adjust length based on detail level
if (detailLevel == DetailLevel.КРАТКО) {
lengthInstruction = "Каждый раздел должен быть кратким (1-2 абзаца).";
} else if (detailLevel == DetailLevel.ПОДРОБНО) {
lengthInstruction = "Каждый раздел должен быть подробным (5-8 абзацев) с глубоким анализом.";
} else {
lengthInstruction = "Каждый раздел должен быть структурированным (3-5 абзацев).";
}
StringBuilder promptBuilder = new StringBuilder();
promptBuilder.append("Проведи комплексный маркетинговый анализ на основе предоставленной информации о бизнесе. ");
promptBuilder.append("Анализ должен быть качественным, прикладным к конкретной тематике и задаче.\n\n");
promptBuilder.append("Включи следующие разделы анализа:\n\n");
// Add section for each analysis type
int sectionNumber = 1;
for (AnalysisType analysisType : analysisTypes) {
promptBuilder.append(sectionNumber).append(". ");
switch (analysisType) {
case РЫНОК:
promptBuilder.append("Анализ рынка: ");
promptBuilder.append("Включи размер рынка, динамику роста, основные сегменты, тренды и перспективы развития.\n");
break;
case КОНКУРЕНТЫ:
promptBuilder.append("Анализ конкурентов: ");
promptBuilder.append("Включи основных конкурентов, их сильные и слабые стороны, позиционирование, ");
promptBuilder.append("ценовую политику и маркетинговые стратегии.\n");
break;
case ЦА:
promptBuilder.append("Анализ целевой аудитории: ");
promptBuilder.append("Включи демографические характеристики, психографический профиль, потребности и боли, ");
promptBuilder.append("поведенческие паттерны и предпочтения.\n");
break;
case КАНАЛЫ:
promptBuilder.append("Анализ маркетинговых каналов: ");
promptBuilder.append("Включи оценку эффективности различных каналов коммуникации, рекомендации по выбору каналов, ");
promptBuilder.append("особенности использования каждого канала и бюджетные рекомендации.\n");
break;
case SWOT:
promptBuilder.append("SWOT-анализ: ");
promptBuilder.append("Включи анализ Сильных сторон (Strengths), Слабых сторон (Weaknesses), ");
promptBuilder.append("Возможностей (Opportunities) и Угроз (Threats). ");
promptBuilder.append("Ответ должен быть структурированным с четким разделением по каждому разделу SWOT.\n");
break;
}
sectionNumber++;
}
promptBuilder.append("\n");
promptBuilder.append(sectionNumber).append(". Общий вывод: ");
promptBuilder.append("Объедини все разделы анализа в единый комплексный вывод, ");
promptBuilder.append("выдели ключевые возможности и особенности бизнеса, ");
promptBuilder.append("сформулируй прикладные рекомендации, применимые к конкретной тематике и задаче.\n\n");
promptBuilder.append(lengthInstruction).append(" ");
promptBuilder.append("Ответ должен быть на русском языке.\n\n");
promptBuilder.append(context);
String prompt = promptBuilder.toString();
return openAIAnalyticsService.generateWithInstruction(context, prompt, "ru");
}
private String generateAnalysisByType(String context, AnalysisType analysisType, DetailLevel detailLevel) {
if (analysisType == null) {
analysisType = AnalysisType.РЫНОК; // Default
@@ -505,15 +566,19 @@ public class MarketingAnalysisService {
markdown.append("- **Слабая сторона:** ").append(request.getWeakSide()).append("\n");
}
String analysisTypeName = (String) reportData.get("analysisType");
if (analysisTypeName != null) {
markdown.append("- **Тип анализа:** ").append(analysisTypeName).append("\n");
@SuppressWarnings("unchecked")
List<String> analysisTypeNames = (List<String>) reportData.get("analysisTypes");
if (analysisTypeNames != null && !analysisTypeNames.isEmpty()) {
markdown.append("- **Типы анализа:** ").append(String.join(", ", analysisTypeNames)).append("\n");
}
markdown.append("\n");
String analysisTitle = analysisTypeName != null ? analysisTypeName : "Резюме анализа";
markdown.append("## ").append(analysisTitle).append("\n\n");
markdown.append(reportData.get("summary")).append("\n\n");
// Display unified analysis
String summary = (String) reportData.get("summary");
if (summary != null && !summary.trim().isEmpty()) {
markdown.append("## Комплексный маркетинговый анализ\n\n");
markdown.append(summary).append("\n\n");
}
@SuppressWarnings("unchecked")
Map<String, Object> targetAudience = (Map<String, Object>) reportData.get("targetAudience");