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,46 +85,30 @@ public class MarketingController {
return unauthorizedResponse(); return unauthorizedResponse();
} }
// Create analysis records (one for each analysis type) // Create unified analysis with all analysis types
List<MarketingAnalysis> analyses = marketingAnalysisService.startAnalysis(request, userId); List<MarketingAnalysis> analyses = marketingAnalysisService.startAnalysis(request, userId);
MarketingAnalysis analysis = analyses.get(0);
// Start async processing for each analysis // Start async processing
for (MarketingAnalysis analysis : analyses) {
marketingAnalysisService.processAnalysis(analysis.getId(), request); marketingAnalysisService.processAnalysis(analysis.getId(), request);
}
// Calculate estimated completion time (5-10 minutes) // Calculate estimated completion time (5-10 minutes)
LocalDateTime estimatedCompletion = LocalDateTime.now().plusMinutes(8); LocalDateTime estimatedCompletion = LocalDateTime.now().plusMinutes(8);
// If multiple analyses, return list of responses // Build analysis types string for message
if (analyses.size() > 1) { String analysisTypesStr = "неизвестно";
List<MarketingAnalysisResponse> responses = analyses.stream() if (analysis.getAnalysisType() != null && !analysis.getAnalysisType().isEmpty()) {
.map(analysis -> new MarketingAnalysisResponse( analysisTypesStr = String.join(", ", analysis.getAnalysisType());
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( MarketingAnalysisResponse response = new MarketingAnalysisResponse(
analysis.getId(), analysis.getId(),
"processing", "processing",
estimatedCompletion, estimatedCompletion,
"Анализ запущен успешно. Результаты будут готовы в течение 5-10 минут."); "Комплексный анализ (" + analysisTypesStr
+ ") запущен успешно. Результаты будут готовы в течение 5-10 минут.");
return ResponseEntity.ok(ApiResponse.success("Анализ запущен успешно", response)); return ResponseEntity.ok(ApiResponse.success("Анализ запущен успешно", response));
} }
}
@GetMapping("/{analysisId}") @GetMapping("/{analysisId}")
public ResponseEntity<?> getAnalysis( public ResponseEntity<?> getAnalysis(
@@ -43,8 +43,7 @@ public class MarketingAnalysisService {
throw new IllegalArgumentException("Необходимо выбрать хотя бы один тип анализа"); throw new IllegalArgumentException("Необходимо выбрать хотя бы один тип анализа");
} }
List<MarketingAnalysis> analyses = new ArrayList<>(); // Create a single unified analysis with all analysis types
for (String analysisType : analysisTypes) {
MarketingAnalysis analysis = new MarketingAnalysis( MarketingAnalysis analysis = new MarketingAnalysis(
request.getBusinessNiche(), request.getBusinessNiche(),
request.getProduct(), request.getProduct(),
@@ -54,16 +53,16 @@ public class MarketingAnalysisService {
request.getDetailLevel(), request.getDetailLevel(),
request.getStrongSide(), request.getStrongSide(),
request.getWeakSide(), request.getWeakSide(),
List.of(analysisType)); // Каждый анализ имеет один тип analysisTypes); // Все типы анализа в одном анализе
analysis.setUserId(userId); analysis.setUserId(userId);
analysis.setStatus("queued"); analysis.setStatus("queued");
addStatusHistoryEntry(analysis, "queued", "Анализ создан и добавлен в очередь"); addStatusHistoryEntry(analysis, "queued", "Комплексный анализ создан и добавлен в очередь");
analysis = repository.save(analysis); analysis = repository.save(analysis);
analyses.add(analysis);
logger.info("Marketing analysis created with ID: {} for user: {} with type: {}", logger.info("Unified marketing analysis created with ID: {} for user: {} with types: {}",
analysis.getId(), userId, analysisType); analysis.getId(), userId, analysisTypes);
}
return analyses; return List.of(analysis);
} }
private void addStatusHistoryEntry(MarketingAnalysis analysis, String status, String message) { 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); logger.info("Starting marketing analysis processing for ID: {}", analysisId);
// Create a modified request with single analysis type for this analysis // Generate marketing report with all analysis types
MarketingAnalysisRequest singleTypeRequest = createSingleTypeRequest(request, Map<String, Object> reportData = generateMarketingReport(request);
analysis.getAnalysisType().get(0));
// Generate marketing report
Map<String, Object> reportData = generateMarketingReport(singleTypeRequest);
// Generate markdown content for PDF // Generate markdown content for PDF
String markdownContent = buildMarkdownFromReport(reportData, singleTypeRequest); String markdownContent = buildMarkdownFromReport(reportData, request);
// Generate PDF // Generate PDF
byte[] pdfBytes = researchPdfService.generatePdfReport( byte[] pdfBytes = researchPdfService.generatePdfReport(
"Маркетинговый анализ: " + singleTypeRequest.getProduct(), "Маркетинговый анализ: " + request.getProduct(),
markdownContent, markdownContent,
new ArrayList<>()); new ArrayList<>());
@@ -137,31 +132,22 @@ 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) { private Map<String, Object> generateMarketingReport(MarketingAnalysisRequest request) {
Map<String, Object> report = new HashMap<>(); Map<String, Object> report = new HashMap<>();
// Get analysis type and detail level - теперь всегда один тип // Get all analysis types and detail level
List<AnalysisType> analysisTypes = request.getAnalysisTypeEnums(); List<AnalysisType> analysisTypes = request.getAnalysisTypeEnums();
AnalysisType analysisType = analysisTypes != null && !analysisTypes.isEmpty() ? analysisTypes.get(0) : null; if (analysisTypes == null || analysisTypes.isEmpty()) {
String analysisTypeName = analysisType != null ? analysisType.getDisplayName() : "Общий"; analysisTypes = List.of(AnalysisType.РЫНОК); // Default
}
DetailLevel detailLevel = request.getDetailLevelEnum(); DetailLevel detailLevel = request.getDetailLevelEnum();
String detailLevelName = detailLevel != null ? detailLevel.getDisplayName() : "Стандартно"; 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 // Build context for AI with all new fields
StringBuilder contextBuilder = new StringBuilder(); StringBuilder contextBuilder = new StringBuilder();
contextBuilder.append("Ниша бизнеса: ").append(request.getBusinessNiche()).append("\n"); contextBuilder.append("Ниша бизнеса: ").append(request.getBusinessNiche()).append("\n");
@@ -208,14 +194,16 @@ public class MarketingAnalysisService {
if (request.getWeakSide() != null && !request.getWeakSide().trim().isEmpty()) { if (request.getWeakSide() != null && !request.getWeakSide().trim().isEmpty()) {
contextBuilder.append("Слабая сторона: ").append(request.getWeakSide()).append("\n"); 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(); String context = contextBuilder.toString();
// Generate analysis based on type and detail level // Generate unified analysis with all types
String analysisContent = generateAnalysisByType(context, analysisType, detailLevel); String unifiedAnalysisContent = generateUnifiedAnalysis(context, analysisTypes, detailLevel);
report.put("analysisType", analysisTypeName);
// Store analysis data
report.put("analysisTypes", analysisTypeNames);
report.put("detailLevel", detailLevelName); report.put("detailLevel", detailLevelName);
report.put("summary", analysisContent != null ? analysisContent : "Анализ не удалось сгенерировать."); report.put("summary", unifiedAnalysisContent != null ? unifiedAnalysisContent : "Анализ не удалось сгенерировать.");
// Generate target audience description (adjusted by detail level) // Generate target audience description (adjusted by detail level)
String audiencePrompt; String audiencePrompt;
@@ -302,6 +290,79 @@ public class MarketingAnalysisService {
return report; 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) { private String generateAnalysisByType(String context, AnalysisType analysisType, DetailLevel detailLevel) {
if (analysisType == null) { if (analysisType == null) {
analysisType = AnalysisType.РЫНОК; // Default analysisType = AnalysisType.РЫНОК; // Default
@@ -505,15 +566,19 @@ public class MarketingAnalysisService {
markdown.append("- **Слабая сторона:** ").append(request.getWeakSide()).append("\n"); markdown.append("- **Слабая сторона:** ").append(request.getWeakSide()).append("\n");
} }
String analysisTypeName = (String) reportData.get("analysisType"); @SuppressWarnings("unchecked")
if (analysisTypeName != null) { List<String> analysisTypeNames = (List<String>) reportData.get("analysisTypes");
markdown.append("- **Тип анализа:** ").append(analysisTypeName).append("\n"); if (analysisTypeNames != null && !analysisTypeNames.isEmpty()) {
markdown.append("- **Типы анализа:** ").append(String.join(", ", analysisTypeNames)).append("\n");
} }
markdown.append("\n"); markdown.append("\n");
String analysisTitle = analysisTypeName != null ? analysisTypeName : "Резюме анализа"; // Display unified analysis
markdown.append("## ").append(analysisTitle).append("\n\n"); String summary = (String) reportData.get("summary");
markdown.append(reportData.get("summary")).append("\n\n"); if (summary != null && !summary.trim().isEmpty()) {
markdown.append("## Комплексный маркетинговый анализ\n\n");
markdown.append(summary).append("\n\n");
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> targetAudience = (Map<String, Object>) reportData.get("targetAudience"); Map<String, Object> targetAudience = (Map<String, Object>) reportData.get("targetAudience");