Files
second-mind-aep/💡 Идеи/💡 Проекты/ERP для малых производств/Архитектура-MVP.md

13 KiB
Raw Blame History

Архитектура MVP: ERP для мастеров

🏗️ Общая архитектура

graph TB
    subgraph "Frontend"
        A[Angular PWA]
        B[QR Scanner]
    end
    
    subgraph "Backend Services"
        C[Go Core Service]
        D[Python Document Service]
    end
    
    subgraph "Infrastructure"
        E[PostgreSQL]
        F[Redis Cache]
    end
    
    A <--> C
    B --> A
    C <--> E
    C <--> D
    D <--> F
    
    style A fill:#ff9999
    style C fill:#99ccff
    style D fill:#99ff99
    style E fill:#ffcc99
    style F fill:#cc99ff

🛠️ Технологический стек

Backend (Go)

  • Framework: Gin (легкий и быстрый)
  • Database: PostgreSQL
  • Authentication: JWT
  • Validation: validator
  • Inter-service Communication: gRPC + Protocol Buffers
  • API Documentation: Swagger/OpenAPI

Frontend (Angular PWA)

  • Framework: Angular 17+
  • Build Tool: Angular CLI
  • PWA: @angular/service-worker
  • QR Scanner: @zxing/ngx-scanner
  • UI: Angular Material + Tailwind CSS
  • State Management: NgRx (для сложной логики)

Document Service (Python)

  • Framework: FastAPI (быстрый, автоматическая документация)
  • PDF Generation: reportlab + weasyprint
  • Office Documents: python-docx, openpyxl
  • Templates: Jinja2
  • Caching: Redis
  • Inter-service Communication: gRPC

Infrastructure

  • Containerization: Docker
  • Orchestration: Docker Compose
  • Inter-service Communication: gRPC + Protocol Buffers
  • API Gateway: Traefik (опционально)
  • Security: HTTPS, CORS, JWT
  • Monitoring: Structured logging + Prometheus

📊 Структура базы данных

ER-диаграмма

erDiagram
    organizations {
        uuid id PK
        varchar name
        varchar type
        jsonb settings
        timestamp created_at
    }
    
    users {
        uuid id PK
        uuid organization_id FK
        varchar email
        varchar role
        timestamp created_at
    }
    
    storage_locations {
        uuid id PK
        uuid organization_id FK
        uuid parent_id FK
        varchar name
        varchar address
        varchar type
        jsonb coordinates
        varchar qr_code
        timestamp created_at
    }
    
    items {
        uuid id PK
        uuid organization_id FK
        varchar name
        text description
        varchar category
        timestamp created_at
    }
    
    item_placements {
        uuid id PK
        uuid organization_id FK
        uuid item_id FK
        uuid location_id FK
        integer quantity
        timestamp created_at
    }
    
    organizations ||--o{ users : "has"
    organizations ||--o{ storage_locations : "has"
    organizations ||--o{ items : "has"
    organizations ||--o{ item_placements : "has"
    
    storage_locations ||--o{ storage_locations : "parent-child"
    storage_locations ||--o{ item_placements : "contains"
    
    items ||--o{ item_placements : "placed_in"

Основные таблицы

-- Организации
CREATE TABLE organizations (
    id UUID PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    type VARCHAR(100),
    settings JSONB,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Пользователи
CREATE TABLE users (
    id UUID PRIMARY KEY,
    organization_id UUID REFERENCES organizations(id),
    email VARCHAR(255) UNIQUE NOT NULL,
    role VARCHAR(50) DEFAULT 'user',
    created_at TIMESTAMP DEFAULT NOW()
);

-- Места хранения
CREATE TABLE storage_locations (
    id UUID PRIMARY KEY,
    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,
    qr_code VARCHAR(255),
    created_at TIMESTAMP DEFAULT NOW()
);

-- Товары
CREATE TABLE items (
    id UUID PRIMARY KEY,
    organization_id UUID REFERENCES organizations(id),
    name VARCHAR(255) NOT NULL,
    description TEXT,
    category VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW()
);

-- Размещение товаров
CREATE TABLE item_placements (
    id UUID PRIMARY KEY,
    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()
);

🔌 API Endpoints

Core Service (Go) - REST API

# Аутентификация
POST   /api/auth/login
POST   /api/auth/register
POST   /api/auth/refresh

# Организации
GET    /api/organizations/:id
PUT    /api/organizations/:id

# Места хранения
GET    /api/locations
POST   /api/locations
GET    /api/locations/:id
PUT    /api/locations/:id
DELETE /api/locations/:id

# Товары
GET    /api/items
POST   /api/items
GET    /api/items/:id
PUT    /api/items/:id
DELETE /api/items/:id

# Операции
POST   /api/operations/place-item
POST   /api/operations/move-item
GET    /api/operations/search

# Шаблоны
GET    /api/templates
POST   /api/templates/:id/apply

Document Service (Python) - REST API

# Документы
POST   /api/documents/generate-pdf
POST   /api/documents/generate-excel
GET    /api/documents/:id/status
GET    /api/documents/:id/download

# Шаблоны документов
GET    /api/templates
POST   /api/templates
PUT    /api/templates/:id
DELETE /api/templates/:id

🔄 Межсервисная коммуникация

gRPC Services

Core Service → Document Service

service DocumentService {
  rpc GenerateQRCode(QRCodeRequest) returns (QRCodeResponse);
  rpc GenerateReport(ReportRequest) returns (ReportResponse);
  rpc GetDocumentStatus(StatusRequest) returns (StatusResponse);
}

Document Service → Core Service

service CoreService {
  rpc GetLocationData(LocationRequest) returns (LocationResponse);
  rpc GetItemData(ItemRequest) returns (ItemResponse);
  rpc ValidateTemplate(TemplateRequest) returns (TemplateResponse);
}

События (Event-Driven)

message DocumentEvent {
  string event_type;  // "qr_generated", "report_ready"
  string document_id;
  string organization_id;
  google.protobuf.Timestamp timestamp;
}

🔄 Диаграммы последовательности

Генерация QR-кода

sequenceDiagram
    participant F as Frontend
    participant C as Core Service
    participant D as Document Service
    participant R as Redis
    
    F->>C: POST /api/locations/:id/qr-code
    C->>D: gRPC GenerateQRCode()
    D->>D: Generate QR code
    D->>R: Cache document
    D->>C: Return document URL
    C->>F: Return QR code data

Размещение товара

sequenceDiagram
    participant U as User
    participant F as Frontend
    participant C as Core Service
    participant DB as Database
    
    U->>F: Scan QR code
    F->>F: Decode location ID
    F->>C: GET /api/locations/:id
    C->>DB: Query location
    DB->>C: Return location data
    C->>F: Return location info
    F->>U: Show location details
    
    U->>F: Select item & quantity
    F->>C: POST /api/operations/place-item
    C->>DB: Create placement
    DB->>C: Confirm placement
    C->>F: Return success
    F->>U: Show confirmation

Поиск товара

sequenceDiagram
    participant U as User
    participant F as Frontend
    participant C as Core Service
    participant R as Redis
    participant DB as Database
    
    U->>F: Search query
    F->>C: GET /api/operations/search?q=query
    C->>R: Check cache
    alt Cache hit
        R->>C: Return cached results
    else Cache miss
        C->>DB: Search items & locations
        DB->>C: Return results
        C->>R: Cache results
    end
    C->>F: Return search results
    F->>U: Display results

🔐 Безопасность

Аутентификация

  • JWT токены с refresh механизмом
  • Organization-scope на всех запросах
  • Middleware для проверки прав доступа

Валидация данных

  • Входная валидация всех параметров
  • SQL injection protection через prepared statements
  • XSS protection в frontend

HTTPS

  • Обязательное использование HTTPS
  • Secure cookies для JWT
  • CORS настройки для PWA

📱 PWA Особенности

Service Worker

  • Кэширование статических ресурсов
  • Offline fallback для базовых функций
  • Background sync для операций

QR Scanner

  • Использование WebRTC для доступа к камере
  • Real-time распознавание QR-кодов
  • Fallback на ручной ввод

Установка

  • Manifest для установки как нативное приложение
  • Splash screen и иконки
  • Автоматические обновления

🚀 Развертывание

Docker Compose

version: '3.8'
services:
  # Core Service (Go)
  core-service:
    build: ./core-service
    ports:
      - "8080:8080"
    environment:
      - DB_HOST=postgres
      - JWT_SECRET=your-secret
      - DOC_SERVICE_URL=http://doc-service:8000
    depends_on:
      - postgres
      - redis

  # Document Service (Python)
  doc-service:
    build: ./doc-service
    ports:
      - "8000:8000"
    environment:
      - REDIS_URL=redis://redis:6379
      - CORE_SERVICE_URL=http://core-service:8080
    depends_on:
      - redis

  # Frontend (Angular)
  frontend:
    build: ./frontend
    ports:
      - "3000:80"
    depends_on:
      - core-service

  # Database
  postgres:
    image: postgres:15
    environment:
      - POSTGRES_DB=erp_mvp
      - POSTGRES_USER=erp_user
      - POSTGRES_PASSWORD=erp_pass
    volumes:
      - postgres_data:/var/lib/postgresql/data

  # Cache
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  # API Gateway (опционально)
  traefik:
    image: traefik:v2.10
    command:
      - --api.insecure=true
      - --providers.docker=true
    ports:
      - "80:80"
      - "8081:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

volumes:
  postgres_data:
  redis_data:

Структура проекта

graph TD
    A[erp-mvp/] --> B[core-service/]
    A --> C[doc-service/]
    A --> D[frontend/]
    A --> E[proto/]
    A --> F[docker-compose.yml]
    
    B --> B1[cmd/]
    B --> B2[internal/]
    B --> B3[pkg/]
    B --> B4[proto/]
    B --> B5[Dockerfile]
    
    C --> C1[app/]
    C --> C2[templates/]
    C --> C3[proto/]
    C --> C4[Dockerfile]
    
    D --> D1[src/]
    D --> D2[angular.json]
    D --> D3[Dockerfile]
    
    E --> E1[core.proto]
    E --> E2[document.proto]
    E --> E3[events.proto]
    
    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#e8f5e8
    style D fill:#fff3e0
    style E fill:#fce4ec

📚 Конкретные библиотеки и фреймворки

Core Service (Go)

// Основные зависимости
go.mod:
- github.com/gin-gonic/gin v1.9.1          // HTTP framework
- github.com/golang-jwt/jwt/v5 v5.0.0      // JWT authentication
- github.com/lib/pq v1.10.9                // PostgreSQL driver
- github.com/go-playground/validator/v10   // Validation
- google.golang.org/grpc v1.58.0           // gRPC client/server
- github.com/swaggo/gin-swagger v1.6.0     // API documentation
- github.com/redis/go-redis/v9 v9.2.1      // Redis client

Document Service (Python)

# requirements.txt
fastapi==0.104.1              # Web framework
uvicorn==0.24.0               # ASGI server
reportlab==4.0.4              # PDF generation
weasyprint==60.1              # HTML to PDF
python-docx==1.1.0            # Word documents
openpyxl==3.1.2               # Excel files
jinja2==3.1.2                 # Templates
redis==5.0.1                  # Redis client
grpcio==1.59.0                # gRPC
protobuf==4.24.4              # Protocol Buffers
pydantic==2.4.2               # Data validation

Frontend (Angular)

// package.json
{
  "dependencies": {
    "@angular/core": "^17.0.0",
    "@angular/material": "^17.0.0",
    "@angular/service-worker": "^17.0.0",
    "@zxing/ngx-scanner": "^3.0.0",
    "@ngrx/store": "^17.0.0",
    "@ngrx/effects": "^17.0.0",
    "tailwindcss": "^3.3.0",
    "rxjs": "^7.8.0"
  }
}

📊 Мониторинг

Логирование

  • Go: logrus или zerolog для structured logging
  • Python: structlog для structured logging
  • Frontend: Angular logging service
  • Correlation ID для отслеживания запросов через все сервисы

Метрики

  • Prometheus для сбора метрик
  • Grafana для визуализации
  • Время отклика API по сервисам
  • Количество ошибок и их типы
  • Активные пользователи и операции

Алерты

  • Высокое время отклика (>500ms)
  • Высокий процент ошибок (>5%)
  • Недоступность сервисов
  • Проблемы с генерацией документов