.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# Исправление NullPointerException в ReportGenerationService
|
||||
|
||||
## Проблема
|
||||
|
||||
Ошибка: `Cannot invoke "java.time.LocalDateTime.toLocalDate()" because "end" is null`
|
||||
|
||||
## Причина
|
||||
|
||||
В методах `generate()` и `simpleGenerate()` класса `ReportGenerationService` код пытался вызвать `end.toLocalDate()` без проверки на null, когда поле `endDate` в `ReportGenerateRequest` было null.
|
||||
|
||||
## Исправления
|
||||
|
||||
### 1. Добавлены значения по умолчанию для дат
|
||||
|
||||
```java
|
||||
// Устанавливаем значения по умолчанию, если даты не указаны
|
||||
if (start == null) {
|
||||
start = LocalDateTime.now().minusDays(30); // 30 дней назад
|
||||
}
|
||||
if (end == null) {
|
||||
end = LocalDateTime.now(); // сейчас
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Исправлены вызовы format() в buildDocx и buildPdf
|
||||
|
||||
```java
|
||||
// Было:
|
||||
req.getStartDate().format(dt), req.getEndDate().format(dt)
|
||||
|
||||
// Стало:
|
||||
req.getStartDate() != null ? req.getStartDate().format(dt) : "не указано",
|
||||
req.getEndDate() != null ? req.getEndDate().format(dt) : "не указано"
|
||||
```
|
||||
|
||||
### 3. Упрощено создание имени файла
|
||||
|
||||
```java
|
||||
// Было:
|
||||
String dateSuffix = end != null ? end.toLocalDate().toString() : "unknown_date";
|
||||
|
||||
// Стало:
|
||||
String dateSuffix = end.toLocalDate().toString(); // end теперь всегда не null
|
||||
```
|
||||
|
||||
## Затронутые методы
|
||||
|
||||
- `generate(ReportGenerateRequest req)`
|
||||
- `simpleGenerate(ReportGenerateRequest req)`
|
||||
- `buildDocx(ReportGenerateRequest req, List<MarketItem> items, Sections sections)`
|
||||
- `buildPdf(ReportGenerateRequest req, List<MarketItem> items, Sections sections)`
|
||||
|
||||
## Результат
|
||||
|
||||
- ✅ Устранена ошибка NullPointerException
|
||||
- ✅ Добавлена обработка случаев, когда даты не указаны
|
||||
- ✅ Установлены разумные значения по умолчанию (последние 30 дней)
|
||||
- ✅ Сохранена обратная совместимость
|
||||
|
||||
## Тестирование
|
||||
|
||||
После исправлений асинхронная генерация отчётов должна работать корректно даже при отсутствии дат в запросе.
|
||||
@@ -103,6 +103,14 @@ public class ReportGenerationService {
|
||||
LocalDateTime start = req.getStartDate();
|
||||
LocalDateTime end = req.getEndDate();
|
||||
|
||||
// Устанавливаем значения по умолчанию, если даты не указаны
|
||||
if (start == null) {
|
||||
start = LocalDateTime.now().minusDays(30); // 30 дней назад
|
||||
}
|
||||
if (end == null) {
|
||||
end = LocalDateTime.now(); // сейчас
|
||||
}
|
||||
|
||||
List<MarketItem> items = marketItemRepository
|
||||
.findByPublishedAtBetween(start, end, org.springframework.data.domain.Pageable.unpaged())
|
||||
.getContent();
|
||||
@@ -128,7 +136,7 @@ public class ReportGenerationService {
|
||||
generated = "(Не удалось сгенерировать текст отчёта по предоставленным данным.)";
|
||||
}
|
||||
|
||||
String filename = "report_simple_" + (end == null ? "date" : end.toLocalDate().toString()) + "-"
|
||||
String filename = "report_simple_" + end.toLocalDate().toString() + "-"
|
||||
+ System.currentTimeMillis() + ".txt";
|
||||
return new ReportBinary(filename, MediaType.TEXT_PLAIN,
|
||||
generated.getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
||||
@@ -150,6 +158,14 @@ public class ReportGenerationService {
|
||||
LocalDateTime start = req.getStartDate();
|
||||
LocalDateTime end = req.getEndDate();
|
||||
|
||||
// Устанавливаем значения по умолчанию, если даты не указаны
|
||||
if (start == null) {
|
||||
start = LocalDateTime.now().minusDays(30); // 30 дней назад
|
||||
}
|
||||
if (end == null) {
|
||||
end = LocalDateTime.now(); // сейчас
|
||||
}
|
||||
|
||||
List<MarketItem> items = marketItemRepository
|
||||
.findByPublishedAtBetween(start, end, org.springframework.data.domain.Pageable.unpaged())
|
||||
.getContent();
|
||||
@@ -157,15 +173,16 @@ public class ReportGenerationService {
|
||||
Sections sections = buildSections(req, items);
|
||||
|
||||
ReportBinary rb;
|
||||
String dateSuffix = end.toLocalDate().toString();
|
||||
if ("DOCX".equalsIgnoreCase(req.getFormat())) {
|
||||
byte[] docx = buildDocx(req, items, sections);
|
||||
String filename = "report_" + end.toLocalDate().toString() + "-" + System.currentTimeMillis() + ".docx";
|
||||
String filename = "report_" + dateSuffix + "-" + System.currentTimeMillis() + ".docx";
|
||||
rb = new ReportBinary(filename,
|
||||
MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
|
||||
docx);
|
||||
} else {
|
||||
byte[] pdf = buildPdf(req, items, sections);
|
||||
String filename = "report_" + end.toLocalDate().toString() + "-" + System.currentTimeMillis() + ".pdf";
|
||||
String filename = "report_" + dateSuffix + "-" + System.currentTimeMillis() + ".pdf";
|
||||
rb = new ReportBinary(filename, MediaType.APPLICATION_PDF, pdf);
|
||||
}
|
||||
persistReport(req, rb);
|
||||
@@ -279,7 +296,8 @@ public class ReportGenerationService {
|
||||
addParagraph(doc, sections.getIntroduction().isBlank()
|
||||
? String.format(
|
||||
"Целью данного отчёта является анализ новостного фона в сфере маркетинга и бизнеса за период с %s по %s. Были проанализированы публикации из ключевых источников для выявления основных трендов.",
|
||||
req.getStartDate().format(dt), req.getEndDate().format(dt))
|
||||
req.getStartDate() != null ? req.getStartDate().format(dt) : "не указано",
|
||||
req.getEndDate() != null ? req.getEndDate().format(dt) : "не указано")
|
||||
: sections.getIntroduction());
|
||||
|
||||
// Main
|
||||
@@ -362,7 +380,8 @@ public class ReportGenerationService {
|
||||
pdf.add(new Paragraph(sections.getIntroduction().isBlank()
|
||||
? String.format(
|
||||
"Целью данного отчёта является анализ новостного фона в сфере маркетинга и бизнеса за период с %s по %s. Были проанализированы публикации из ключевых источников для выявления основных трендов.",
|
||||
req.getStartDate().format(dt), req.getEndDate().format(dt))
|
||||
req.getStartDate() != null ? req.getStartDate().format(dt) : "не указано",
|
||||
req.getEndDate() != null ? req.getEndDate().format(dt) : "не указано")
|
||||
: sections.getIntroduction()));
|
||||
|
||||
pdf.add(new Paragraph("Основная часть"));
|
||||
|
||||
Reference in New Issue
Block a user