Files
Mini-ERP-app/core-service/.cursor/plan.md
Andrey Epifantsev 9777114e16 feat: завершён этап 1 - Фундамент Core Service
- Удалены зависимости: grpc, redis, prometheus
- Упрощена конфигурация (Server, Database, JWT)
- Создан логгер на основе logrus
- Добавлено подключение к PostgreSQL
- Создана миграция с базовыми таблицами
- Обновлены модели с валидацией
- Создан базовый API сервер с health check
- Добавлен .env.example

Готово для этапа 2 - Аутентификация
2025-08-27 14:40:48 +04:00

506 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Детальный план разработки Core Service
## 🎯 Цель
Реализация Core Service для ERP MVP с упрощённой архитектурой: Go + PostgreSQL + REST API без gRPC, Redis и Document Service.
## 📋 Общие принципы
- **REST API** вместо gRPC
- **PostgreSQL** как единственная БД (без Redis)
- **JWT аутентификация** с organization-scope
- **Структурированное логирование** (без Prometheus на MVP)
- **Валидация данных** на всех уровнях
---
## 🚀 Этап 1: Фундамент (Недели 1-2)
### Шаг 1.1: Очистка и настройка проекта
- [x] Удалить зависимости: `grpc`, `redis`, `prometheus`
- [x] Обновить `go.mod` - оставить только необходимые пакеты
- [x] Настроить структуру проекта согласно Go standards
- [x] Добавить `.env` для конфигурации
**Файлы для изменения:**
```
go.mod - удалить grpc, redis, prometheus ✅
cmd/main.go - убрать redis, grpc клиенты ✅
internal/config/config.go - упростить конфигурацию ✅
```
### Шаг 1.2: Базовая конфигурация
- [x] Создать `internal/config/config.go` с упрощённой структурой
- [x] Добавить поддержку `.env` файлов
- [x] Настроить логирование через logrus
- [x] Добавить health check endpoint
**Структура конфигурации:**
```go
type Config struct {
Server ServerConfig
Database DatabaseConfig
JWT JWTConfig
}
type ServerConfig struct {
Port string
Host string
}
type DatabaseConfig struct {
Host string
Port string
User string
Password string
DBName string
SSLMode string
}
type JWTConfig struct {
Secret string
TTL time.Duration
}
```
### Шаг 1.3: Подключение к базе данных
- [x] Создать `internal/database/connection.go`
- [x] Настроить подключение к PostgreSQL
- [x] Добавить миграции через `golang-migrate`
- [x] Создать базовые таблицы
**Структура БД (упрощённая):**
```sql
-- organizations
CREATE TABLE organizations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(255) NOT NULL,
type VARCHAR(100),
settings JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
-- users
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(50) DEFAULT 'user',
created_at TIMESTAMP DEFAULT NOW()
);
-- storage_locations
CREATE TABLE storage_locations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
parent_id UUID REFERENCES storage_locations(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
address VARCHAR(100) NOT NULL,
type VARCHAR(50) NOT NULL,
coordinates JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
-- items
CREATE TABLE items (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
category VARCHAR(100),
created_at TIMESTAMP DEFAULT NOW()
);
-- item_placements
CREATE TABLE item_placements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
item_id UUID REFERENCES items(id) ON DELETE CASCADE,
location_id UUID REFERENCES storage_locations(id) ON DELETE CASCADE,
quantity INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW()
);
```
### Шаг 1.4: Базовые модели
- [x] Создать `internal/models/` с основными структурами
- [x] Добавить валидацию через `validator`
- [x] Реализовать JSON теги для API
**Основные модели:**
```go
// internal/models/organization.go
type Organization struct {
ID uuid.UUID `json:"id" db:"id"`
Name string `json:"name" validate:"required"`
Type string `json:"type"`
Settings JSON `json:"settings"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
// internal/models/user.go
type User struct {
ID uuid.UUID `json:"id" db:"id"`
OrganizationID uuid.UUID `json:"organization_id" db:"organization_id"`
Email string `json:"email" validate:"required,email"`
PasswordHash string `json:"-" db:"password_hash"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
// internal/models/storage_location.go
type StorageLocation struct {
ID uuid.UUID `json:"id" db:"id"`
OrganizationID uuid.UUID `json:"organization_id" db:"organization_id"`
ParentID *uuid.UUID `json:"parent_id,omitempty" db:"parent_id"`
Name string `json:"name" validate:"required"`
Address string `json:"address" validate:"required"`
Type string `json:"type" validate:"required"`
Coordinates JSON `json:"coordinates"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
// internal/models/item.go
type Item struct {
ID uuid.UUID `json:"id" db:"id"`
OrganizationID uuid.UUID `json:"organization_id" db:"organization_id"`
Name string `json:"name" validate:"required"`
Description string `json:"description"`
Category string `json:"category"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
// internal/models/item_placement.go
type ItemPlacement struct {
ID uuid.UUID `json:"id" db:"id"`
OrganizationID uuid.UUID `json:"organization_id" db:"organization_id"`
ItemID uuid.UUID `json:"item_id" db:"item_id"`
LocationID uuid.UUID `json:"location_id" db:"location_id"`
Quantity int `json:"quantity" validate:"min=1"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
}
```
---
## 🔐 Этап 2: Аутентификация (Неделя 2)
### Шаг 2.1: JWT аутентификация
- [ ] Создать `internal/auth/jwt.go`
- [ ] Реализовать генерацию и валидацию JWT токенов
- [ ] Добавить organization-scope в токены
- [ ] Создать middleware для проверки аутентификации
**JWT структура:**
```go
type Claims struct {
UserID uuid.UUID `json:"user_id"`
OrganizationID uuid.UUID `json:"organization_id"`
Email string `json:"email"`
Role string `json:"role"`
jwt.RegisteredClaims
}
```
### Шаг 2.2: Хеширование паролей
- [ ] Создать `internal/auth/password.go`
- [ ] Использовать bcrypt для хеширования
- [ ] Добавить функции проверки паролей
### Шаг 2.3: API endpoints для аутентификации
- [ ] `POST /api/auth/register` - регистрация организации и пользователя
- [ ] `POST /api/auth/login` - вход в систему
- [ ] `POST /api/auth/refresh` - обновление токена (опционально)
**Структура запросов:**
```go
type RegisterRequest struct {
OrganizationName string `json:"organization_name" validate:"required"`
UserEmail string `json:"user_email" validate:"required,email"`
UserPassword string `json:"user_password" validate:"required,min=8"`
OrganizationType string `json:"organization_type"`
}
type LoginRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}
```
---
## 🏗️ Этап 3: API структура (Неделя 3)
### Шаг 3.1: Базовые handlers
- [ ] Создать `internal/api/handlers/` с базовыми структурами
- [ ] Реализовать middleware для CORS, логирования, аутентификации
- [ ] Добавить обработку ошибок
**Структура handlers:**
```
internal/api/
├── handlers/
│ ├── auth.go
│ ├── organizations.go
│ ├── locations.go
│ ├── items.go
│ └── operations.go
├── middleware/
│ ├── auth.go
│ ├── cors.go
│ ├── logging.go
│ └── error_handler.go
└── server.go
```
### Шаг 3.2: Repository pattern
- [ ] Создать `internal/repository/` для работы с БД
- [ ] Реализовать CRUD операции для всех сущностей
- [ ] Добавить organization-scope фильтрацию
**Основные репозитории:**
```go
// internal/repository/organizations.go
type OrganizationRepository interface {
Create(ctx context.Context, org *models.Organization) error
GetByID(ctx context.Context, id uuid.UUID) (*models.Organization, error)
Update(ctx context.Context, org *models.Organization) error
}
// internal/repository/users.go
type UserRepository interface {
Create(ctx context.Context, user *models.User, password string) error
GetByEmail(ctx context.Context, email string) (*models.User, error)
GetByID(ctx context.Context, id uuid.UUID) (*models.User, error)
}
// internal/repository/locations.go
type LocationRepository interface {
Create(ctx context.Context, location *models.StorageLocation) error
GetByID(ctx context.Context, id uuid.UUID, orgID uuid.UUID) (*models.StorageLocation, error)
GetByOrganization(ctx context.Context, orgID uuid.UUID) ([]*models.StorageLocation, error)
Update(ctx context.Context, location *models.StorageLocation) error
Delete(ctx context.Context, id uuid.UUID, orgID uuid.UUID) error
}
// internal/repository/items.go
type ItemRepository interface {
Create(ctx context.Context, item *models.Item) error
GetByID(ctx context.Context, id uuid.UUID, orgID uuid.UUID) (*models.Item, error)
GetByOrganization(ctx context.Context, orgID uuid.UUID) ([]*models.Item, error)
Search(ctx context.Context, orgID uuid.UUID, query string) ([]*models.Item, error)
Update(ctx context.Context, item *models.Item) error
Delete(ctx context.Context, id uuid.UUID, orgID uuid.UUID) error
}
```
### Шаг 3.3: Service layer
- [ ] Создать `internal/service/` для бизнес-логики
- [ ] Реализовать валидацию и обработку данных
- [ ] Добавить транзакции для сложных операций
---
## 📍 Этап 4: Шаблоны помещений (Неделя 4)
### Шаг 4.1: Система шаблонов
- [ ] Создать `internal/templates/` для шаблонов помещений
- [ ] Реализовать 3 базовых шаблона: Гараж, Мастерская, Склад
- [ ] Добавить генерацию адресов мест
**Шаблоны:**
```go
type Template struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Zones []Zone `json:"zones"`
AddressRules []AddressRule `json:"address_rules"`
}
type Zone struct {
Name string `json:"name"`
Type string `json:"type"` // "cabinet", "floor", "table"
Rows int `json:"rows"`
Columns int `json:"columns"`
Position Position `json:"position"`
}
type AddressRule struct {
ZoneType string `json:"zone_type"`
Prefix string `json:"prefix"`
Format string `json:"format"` // "Ш{zone}-П{row}-Я{col}"
}
```
### Шаг 4.2: API для шаблонов
- [ ] `GET /api/templates` - список доступных шаблонов
- [ ] `POST /api/templates/:id/apply` - применение шаблона к организации
- [ ] Генерация мест хранения из шаблона
### Шаг 4.3: Адресация мест
- [ ] Реализовать систему адресации (Ш1-П2-Я3, З1-У2)
- [ ] Автоматическая генерация адресов при создании мест
- [ ] Валидация уникальности адресов в рамках организации
---
## 🔍 Этап 5: Операции (Неделя 5)
### Шаг 5.1: Размещение товаров
- [ ] `POST /api/operations/place-item` - размещение товара
- [ ] Валидация доступности места
- [ ] Обновление статуса места
- [ ] Логирование операций
**Структура запроса:**
```go
type PlaceItemRequest struct {
ItemID uuid.UUID `json:"item_id" validate:"required"`
LocationID uuid.UUID `json:"location_id" validate:"required"`
Quantity int `json:"quantity" validate:"required,min=1"`
}
```
### Шаг 5.2: Поиск товаров
- [ ] `GET /api/operations/search` - поиск по названию, адресу, категории
- [ ] Оптимизация запросов через индексы
- [ ] Пагинация результатов
**Параметры поиска:**
```go
type SearchRequest struct {
Query string `form:"q"`
Category string `form:"category"`
Address string `form:"address"`
Page int `form:"page,default=1"`
PageSize int `form:"page_size,default=20"`
}
```
### Шаг 5.3: Перемещение товаров
- [ ] `POST /api/operations/move-item` - перемещение между местами
- [ ] Валидация наличия товара в исходном месте
- [ ] Атомарность операции через транзакции
---
## 🧪 Этап 6: Тестирование и полировка (Неделя 6)
### Шаг 6.1: Unit тесты
- [ ] Тесты для всех репозиториев
- [ ] Тесты для сервисов
- [ ] Тесты для handlers
- [ ] Покрытие кода > 80%
### Шаг 6.2: Интеграционные тесты
- [ ] Тесты API endpoints
- [ ] Тесты с реальной БД
- [ ] Тесты аутентификации
### Шаг 6.3: Производительность
- [ ] Оптимизация SQL запросов
- [ ] Добавление индексов
- [ ] Тестирование под нагрузкой
- [ ] Мониторинг медленных запросов
### Шаг 6.4: Документация API
- [ ] Swagger/OpenAPI документация
- [ ] Примеры запросов и ответов
- [ ] Описание ошибок
---
## 📊 Критерии готовности
### Функциональные критерии
- [ ] Все CRUD операции работают для items, locations
- [ ] Аутентификация с organization-scope
- [ ] Шаблоны помещений генерируют структуру
- [ ] Операции размещения/поиска/перемещения работают
- [ ] API отвечает на все запросы
### Технические критерии
- [ ] Время отклика API ≤ 200мс
- [ ] Покрытие тестами > 80%
- [ ] Все endpoints документированы
- [ ] Логирование работает корректно
- [ ] Graceful shutdown реализован
### Безопасность
- [ ] JWT токены валидируются
- [ ] Organization-scope на всех данных
- [ ] Валидация входных данных
- [ ] SQL injection protection
---
## 🚨 Риски и митигация
### Высокий риск
- **Производительность БД при большом количестве данных**
- Митигация: Индексы, пагинация, мониторинг запросов
### Средний риск
- **JWT токены без refresh механизма**
- Митигация: Короткий TTL, возможность перелогина
### Низкий риск
- **Отсутствие кэширования**
- Митигация: Оптимизация SQL, индексы
---
## 📁 Структура проекта (финальная)
```
app/core-service/
├── cmd/
│ └── main.go
├── internal/
│ ├── api/
│ │ ├── handlers/
│ │ ├── middleware/
│ │ └── server.go
│ ├── auth/
│ │ ├── jwt.go
│ │ └── password.go
│ ├── config/
│ │ └── config.go
│ ├── database/
│ │ ├── connection.go
│ │ └── migrations/
│ ├── models/
│ │ ├── organization.go
│ │ ├── user.go
│ │ ├── storage_location.go
│ │ ├── item.go
│ │ └── item_placement.go
│ ├── repository/
│ │ ├── organizations.go
│ │ ├── users.go
│ │ ├── locations.go
│ │ └── items.go
│ ├── service/
│ │ ├── auth_service.go
│ │ ├── location_service.go
│ │ └── item_service.go
│ └── templates/
│ ├── templates.go
│ └── address_rules.go
├── migrations/
├── tests/
├── go.mod
├── go.sum
├── Dockerfile
└── .env.example
```
---
## 🎯 Следующие шаги после Core Service
1. **Frontend разработка** - Angular PWA с QR сканером
2. **Интеграция** - тестирование API с фронтендом
3. **Пилот** - тестирование с реальными пользователями
4. **Мониторинг** - сбор метрик и обратной связи