### **Техническое задание №1: Основа проекта, модели данных и репозитории** **Цель:** Создать фундамент backend-приложения для модуля SMM-автоматизации. На этом этапе необходимо инициализировать проект, определить структуру базы данных с помощью JPA-сущностей и создать репозитории для доступа к данным. --- ## 1\. Инициализация проекта - **Задача:** Создать новый проект на базе **Spring Boot**. - **Технологический стек:** - **Фреймворк:** Spring Boot 3.x - **Язык:** Java 17 (или выше) - **Сборщик:** Maven - **Артефакт:** `smm-automation-service` --- ## 2\. Зависимости В `pom.xml` необходимо добавить следующие ключевые зависимости: - **Spring Web:** для создания REST-контроллеров. - **Spring Data JPA:** для работы с базой данных через сущности. - **PostgreSQL Driver:** для подключения к базе данных PostgreSQL. - **Lombok:** для сокращения шаблонного кода в моделях (геттеры, сеттеры, конструкторы). - **Hibernate Types:** для поддержки типа данных JSON в PostgreSQL. --- ## 3\. Модели данных (JPA Entities) Необходимо создать Java-классы, описывающие таблицы в базе данных, со всеми указанными полями, типами и связями. ### `Channel.java` Канал для публикации (Telegram, VK и т.д.). ```java import jakarta.persistence.*; import java.util.UUID; @Entity @Table(name = "channels") public class Channel { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; // e.g., "Telegram Official" @Enumerated(EnumType.STRING) private ChannelType type; // ENUM: TELEGRAM, VK, INSTAGRAM private String apiKeyRef; // Ссылка на secret в Vault или аналоге private boolean isActive; } // Необходимо также создать Enum ChannelType public enum ChannelType { TELEGRAM, VK, INSTAGRAM } ``` ### `Campaign.java` Маркетинговая кампания. ```java import jakarta.persistence.*; import java.math.BigDecimal; import java.time.ZonedDateTime; import java.util.UUID; @Entity @Table(name = "campaigns") public class Campaign { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private String name; private String goal; private BigDecimal budget; private ZonedDateTime startAt; private ZonedDateTime endAt; @Enumerated(EnumType.STRING) private CampaignStatus status; // ENUM: PLANNED, ACTIVE, COMPLETED } // Enum CampaignStatus public enum CampaignStatus { PLANNED, ACTIVE, COMPLETED } ``` ### `ContentQueue.java` Очередь контента для публикации. ```java import jakarta.persistence.*; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.type.SqlTypes; import java.time.ZonedDateTime; import java.util.UUID; @Entity @Table(name = "content_queue") public class ContentQueue { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "campaign_id") private Campaign campaign; private String locale; // e.g., "ru", "kk" private String topic; @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private String postDraft; // JSON: { "title": "...", "body": "...", "hashtags": [...] } @JdbcTypeCode(SqlTypes.JSON) @Column(columnDefinition = "jsonb") private String assetsRefs; // JSON: ["path/to/image1.jpg"] private ZonedDateTime scheduledAt; private int priority; @Enumerated(EnumType.STRING) private ContentStatus status; // ENUM: DRAFT, PENDING_APPROVAL, APPROVED, PUBLISHED, FAILED } // Enum ContentStatus public enum ContentStatus { DRAFT, PENDING_APPROVAL, APPROVED, PUBLISHED, FAILED } ``` ### `Message.java` Факт публикации сообщения. ```java import jakarta.persistence.*; import java.time.ZonedDateTime; import java.util.UUID; @Entity @Table(name = "messages") public class Message { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "channel_id") private Channel channel; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "content_id") private ContentQueue content; private String externalId; // ID поста в соцсети private String url; private ZonedDateTime postedAt; } ``` ### `KpiSnapshot.java` Срезы по ключевым метрикам. ```java import jakarta.persistence.*; import java.math.BigDecimal; import java.time.LocalDate; import java.util.UUID; @Entity @Table(name = "kpi_snapshots") public class KpiSnapshot { @Id @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; private LocalDate date; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "channel_id") private Channel channel; private String metric; // e.g., "CTR", "ER", "LEADS" private BigDecimal value; } ``` --- ## 4\. Репозитории (Spring Data JPA) Для каждой созданной сущности необходимо создать соответствующий интерфейс-репозиторий для взаимодействия с базой данных. - `ChannelRepository.java` - `CampaignRepository.java` - `ContentQueueRepository.java` - `MessageRepository.java` - `KpiSnapshotRepository.java` **Пример для `CampaignRepository`:** ```java import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.UUID; @Repository public interface CampaignRepository extends JpaRepository { // Здесь в будущем можно будет добавлять кастомные методы для запросов } ``` --- ## 5\. Конфигурация базы данных В файле `application.properties` или `application.yml` необходимо указать настройки для подключения к локальной или dev-базе данных PostgreSQL. **Пример для `application.yml`:** ```yaml spring: datasource: url: jdbc:postgresql://localhost:5432/smm_automation_db username: your_username password: your_password jpa: hibernate: ddl-auto: update # На время разработки, для prod использовать 'validate' properties: hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect format_sql: true show-sql: true ``` --- ## Критерии выполнения - Проект Spring Boot успешно создан и запускается без ошибок. - Все 5 JPA-сущностей и 3 Enum'а созданы в проекте. - Для каждой сущности создан соответствующий Spring Data JPA репозиторий. - Приложение успешно подключается к базе данных PostgreSQL. - При запуске приложения Hibernate автоматически создает или обновляет таблицы в базе данных в соответствии с описанными моделями.