269 lines
7.8 KiB
Markdown
269 lines
7.8 KiB
Markdown
### **Техническое задание №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 автоматически создает или обновляет таблицы в базе данных в соответствии с описанными моделями.
|