Добавлен план реализации Core сервиса
This commit is contained in:
504
core-service/.cursor/plan.md
Normal file
504
core-service/.cursor/plan.md
Normal file
@@ -0,0 +1,504 @@
|
|||||||
|
# Детальный план разработки 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: Очистка и настройка проекта
|
||||||
|
- [ ] Удалить зависимости: `grpc`, `redis`, `prometheus`
|
||||||
|
- [ ] Обновить `go.mod` - оставить только необходимые пакеты
|
||||||
|
- [ ] Настроить структуру проекта согласно Go standards
|
||||||
|
- [ ] Добавить `.env` для конфигурации
|
||||||
|
|
||||||
|
**Файлы для изменения:**
|
||||||
|
```
|
||||||
|
go.mod - удалить grpc, redis, prometheus
|
||||||
|
cmd/main.go - убрать redis, grpc клиенты
|
||||||
|
internal/config/config.go - упростить конфигурацию
|
||||||
|
```
|
||||||
|
|
||||||
|
### Шаг 1.2: Базовая конфигурация
|
||||||
|
- [ ] Создать `internal/config/config.go` с упрощённой структурой
|
||||||
|
- [ ] Добавить поддержку `.env` файлов
|
||||||
|
- [ ] Настроить логирование через logrus
|
||||||
|
- [ ] Добавить 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: Подключение к базе данных
|
||||||
|
- [ ] Создать `internal/database/connection.go`
|
||||||
|
- [ ] Настроить подключение к PostgreSQL
|
||||||
|
- [ ] Добавить миграции через `golang-migrate`
|
||||||
|
- [ ] Создать базовые таблицы
|
||||||
|
|
||||||
|
**Структура БД (упрощённая):**
|
||||||
|
```sql
|
||||||
|
-- organizations
|
||||||
|
CREATE TABLE organizations (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
type VARCHAR(100),
|
||||||
|
settings JSONB,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- users
|
||||||
|
CREATE TABLE users (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
organization_id UUID REFERENCES organizations(id),
|
||||||
|
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 gen_random_uuid(),
|
||||||
|
organization_id UUID REFERENCES organizations(id),
|
||||||
|
parent_id UUID REFERENCES storage_locations(id),
|
||||||
|
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 gen_random_uuid(),
|
||||||
|
organization_id UUID REFERENCES organizations(id),
|
||||||
|
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 gen_random_uuid(),
|
||||||
|
organization_id UUID REFERENCES organizations(id),
|
||||||
|
item_id UUID REFERENCES items(id),
|
||||||
|
location_id UUID REFERENCES storage_locations(id),
|
||||||
|
quantity INTEGER DEFAULT 1,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Шаг 1.4: Базовые модели
|
||||||
|
- [ ] Создать `internal/models/` с основными структурами
|
||||||
|
- [ ] Добавить валидацию через `validator`
|
||||||
|
- [ ] Реализовать 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"`
|
||||||
|
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. **Мониторинг** - сбор метрик и обратной связи
|
||||||
Reference in New Issue
Block a user