### **Техническое задание №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<Campaign, UUID> {
    // Здесь в будущем можно будет добавлять кастомные методы для запросов
}
```

---

## 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 автоматически создает или обновляет таблицы в базе данных в соответствии с описанными моделями.
