all types of analyses
This commit is contained in:
@@ -85,45 +85,29 @@ 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(
|
|
||||||
analysis.getId(),
|
|
||||||
"processing",
|
|
||||||
estimatedCompletion,
|
|
||||||
"Анализ запущен успешно. Результаты будут готовы в течение 5-10 минут.");
|
|
||||||
return ResponseEntity.ok(ApiResponse.success("Анализ запущен успешно", response));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MarketingAnalysisResponse response = new MarketingAnalysisResponse(
|
||||||
|
analysis.getId(),
|
||||||
|
"processing",
|
||||||
|
estimatedCompletion,
|
||||||
|
"Комплексный анализ (" + analysisTypesStr
|
||||||
|
+ ") запущен успешно. Результаты будут готовы в течение 5-10 минут.");
|
||||||
|
return ResponseEntity.ok(ApiResponse.success("Анализ запущен успешно", response));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{analysisId}")
|
@GetMapping("/{analysisId}")
|
||||||
|
|||||||
@@ -43,27 +43,26 @@ 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(),
|
request.getTargetAudience(),
|
||||||
request.getTargetAudience(),
|
request.getRegion(),
|
||||||
request.getRegion(),
|
request.getGoal(),
|
||||||
request.getGoal(),
|
request.getDetailLevel(),
|
||||||
request.getDetailLevel(),
|
request.getStrongSide(),
|
||||||
request.getStrongSide(),
|
request.getWeakSide(),
|
||||||
request.getWeakSide(),
|
analysisTypes); // Все типы анализа в одном анализе
|
||||||
List.of(analysisType)); // Каждый анализ имеет один тип
|
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("Unified marketing analysis created with ID: {} for user: {} with types: {}",
|
||||||
logger.info("Marketing analysis created with ID: {} for user: {} with type: {}",
|
analysis.getId(), userId, analysisTypes);
|
||||||
analysis.getId(), userId, analysisType);
|
|
||||||
}
|
return List.of(analysis);
|
||||||
return analyses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,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) {
|
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();
|
||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user