diff --git a/README.md b/README.md
index ee9d69b..7ad25d2 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,21 @@
4. Найденный в соответствии с условием задачи месяц должен выводиться на английском языке в нижнем регистре. Если месяцев несколько, то на вывод они все подаются на английском языке в нижнем регистре в порядке их следования в течение года.
## Автор решения
+Стаценко Михаил Александрович
## Описание реализации
+Для выполнения поставленной задачи разработано консольное Spring Boot приложение.
+
+Первым аргументом командной строки передается путь к файлу с исходными данными. `ReportService` в методе `generateReport` при помощи вспомогательных методов читает json файл по указанному пути, затем считает сумму, потраченную пользователями для каждого месяца, после чего находит месяц(-ы) с максимальной суммой и возвращает строку в формате json в соответствии с заданием.
+
+Поскольку речь идет об анализе заказов на маркетплейсе, отчет, вероятно, будет создаваться на основании миллионов заказов, поэтому для подсчета суммы, потраченной пользователями по месяцам используется параллельная обработка, а файл с исходными данными читается при помощи `BufferedReader`.
## Инструкция по сборке и запуску решения
+На тестовом стенде должны быть установлены Maven и Java 21+ версии
+
+Сначала необходимо клонировать репозиторий на локальную машину:
+`git clone https://github.com/MikhailStatsenko/school2024-test-task1.git`
+
+Затем нужно перейти в склонированную директорию и последовательно выполнить команды:
+`mvn clean package`
+`java -jar target/analytics-1.0.jar [путь к файлу с исходными данными]`
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..8ee326d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,83 @@
+
+
+ 4.0.0
+
+ edu.croc
+ analytics
+ 1.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.2
+
+
+
+
+ UTF-8
+ UTF-8
+
+ 21
+
+ 21
+ 21
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ 2.17.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ prepare-package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/lib
+ false
+ false
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ lib/
+ edu.croc.analytics.AnalyticsApplication
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/edu/croc/analytics/AnalyticsApplication.java b/src/main/java/edu/croc/analytics/AnalyticsApplication.java
new file mode 100644
index 0000000..8bf0563
--- /dev/null
+++ b/src/main/java/edu/croc/analytics/AnalyticsApplication.java
@@ -0,0 +1,29 @@
+package edu.croc.analytics;
+
+import edu.croc.analytics.service.ReportService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@Slf4j
+@SpringBootApplication
+@RequiredArgsConstructor
+public class AnalyticsApplication implements CommandLineRunner {
+ private final ReportService reportService;
+
+ public static void main(String[] args) {
+ SpringApplication.run(AnalyticsApplication.class, args);
+ }
+
+ @Override
+ public void run(String... args) {
+ try {
+ String report = reportService.generateReport(args[0]);
+ System.out.println(report);
+ } catch (Exception e) {
+ log.error("Error generating report", e);
+ }
+ }
+}
diff --git a/src/main/java/edu/croc/analytics/configuration/ApplicationConfiguration.java b/src/main/java/edu/croc/analytics/configuration/ApplicationConfiguration.java
new file mode 100644
index 0000000..5543903
--- /dev/null
+++ b/src/main/java/edu/croc/analytics/configuration/ApplicationConfiguration.java
@@ -0,0 +1,15 @@
+package edu.croc.analytics.configuration;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ApplicationConfiguration {
+ @Bean
+ public ObjectMapper objectMapper() {
+ return JsonMapper.builder().addModule(new JavaTimeModule()).build();
+ }
+}
diff --git a/src/main/java/edu/croc/analytics/dto/Order.java b/src/main/java/edu/croc/analytics/dto/Order.java
new file mode 100644
index 0000000..27263dd
--- /dev/null
+++ b/src/main/java/edu/croc/analytics/dto/Order.java
@@ -0,0 +1,27 @@
+package edu.croc.analytics.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+public record Order (
+ @JsonProperty("user_id")
+ String userId,
+
+ @JsonProperty("ordered_at")
+ LocalDateTime orderedAt,
+
+ @JsonProperty("status")
+ Status status,
+
+ @JsonProperty("total")
+ BigDecimal total) {
+
+ public enum Status {
+ COMPLETED,
+ CANCELED,
+ CREATED,
+ DELIVERY
+ }
+}
diff --git a/src/main/java/edu/croc/analytics/service/ReportService.java b/src/main/java/edu/croc/analytics/service/ReportService.java
new file mode 100644
index 0000000..bf0d0fc
--- /dev/null
+++ b/src/main/java/edu/croc/analytics/service/ReportService.java
@@ -0,0 +1,69 @@
+package edu.croc.analytics.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import edu.croc.analytics.dto.Order;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.time.Month;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ReportService {
+ private final ObjectMapper mapper;
+
+ private record Report(List months) {}
+
+ public String generateReport(String filePath) throws IOException {
+ Order[] orders = readOrdersJson(filePath);
+
+ Map totals = getTotalByMonth(orders);
+
+ List months = getMaxTotalMonths(totals);
+ return mapper.writeValueAsString(new Report(months));
+ }
+
+ private Order[] readOrdersJson(String filePath) throws IOException {
+ try(var source = new BufferedReader(
+ new InputStreamReader(new FileInputStream(filePath), StandardCharsets.UTF_8))) {
+ return mapper.readValue(source, Order[].class);
+ }
+ }
+
+ private Map getTotalByMonth(Order[] orders) {
+ Map totals = new ConcurrentHashMap<>(Month.values().length);
+ for (Month month : Month.values()) {
+ totals.put(month, BigDecimal.ZERO);
+ }
+
+ Arrays.stream(orders).parallel()
+ .filter(order -> order.status().equals(Order.Status.COMPLETED))
+ .forEach(order -> totals.compute(
+ order.orderedAt().getMonth(),
+ (moth, currentMothTotal) -> currentMothTotal.add(order.total()))
+ );
+ return totals;
+ }
+
+ private List getMaxTotalMonths(Map totals) {
+ BigDecimal max = Collections.max(totals.values());
+
+ List result = new ArrayList<>();
+ for (Month month : Month.values()) {
+ if (totals.get(month).compareTo(max) == 0) {
+ result.add(month.name().toLowerCase());
+ }
+ }
+ return result;
+ }
+}