From a55cf6026ca639b28b65f040e24e850da2dfef02 Mon Sep 17 00:00:00 2001 From: neo Date: Sat, 20 Jun 2026 18:01:54 +0500 Subject: [PATCH] Initial project plan and architecture --- ARCHITECTURE.md | 318 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 166 ++++++++++++++++++++++++- 2 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..3b10fff --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,318 @@ +# ROI24 — Техническая архитектура + +## Общая схема + +``` +┌──────────────────────────────────────────────────────────────┐ +│ ИСТОЧНИКИ ДАННЫХ │ +│ 1С:Предприятие │ Банки │ CRM │ Реклама │ Маркетплейсы │ +└────────┬─────────┬───────┬─────┬────────┴───────────────────┘ + │ │ │ │ + ┌────▼────┐ ┌──▼────┐ │ │ + │ 1C Ad. │ │Bank. │ │Ad. │ │CRM Ad. │ + └────┬────┘ └──┬────┘ │ └──┬──────┘ + │ │ │ │ + ┌────▼─────────▼───────▼───────▼─────────┐ + │ Python ETL Pipeline │ + │ APScheduler / Celery + Redis │ + └─────────────────┬──────────────────────┘ + │ + ┌─────────────────▼──────────────────────┐ + │ PostgreSQL 16 │ + │ raw_data │ aggregated │ metadata │ + └─────────────────┬──────────────────────┘ + │ + ┌─────────────────▼──────────────────────┐ + │ FastAPI (REST API) │ + │ GET /api/dashboard/{client_id} │ + │ GET /api/metrics/{client_id}/{type} │ + │ GET /api/trend/{client_id} │ + └─────────────────┬──────────────────────┘ + │ + ┌─────────────────▼──────────────────────┐ + │ HTML Dashboard (ECharts) │ + │ Single-page SPA или server-rendered │ + └────────────────────────────────────────┘ +``` + +## Схема БД (PostgreSQL) + +```sql +-- Клиент +CREATE TABLE clients ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name VARCHAR(256) NOT NULL, + niche VARCHAR(100), -- ecommerce, services, retail, b2b + status VARCHAR(20) DEFAULT 'active', + plan VARCHAR(20) DEFAULT 'start', -- start, business, premium + created_at TIMESTAMP DEFAULT NOW() +); + +-- Подключённые источники данных +CREATE TABLE data_sources ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + client_id UUID REFERENCES clients(id), + source_type VARCHAR(50), -- 1c, bank, ad_platform, crm + source_name VARCHAR(100), -- СберБизнес, Яндекс.Директ, amoCRM + config JSONB NOT NULL, -- credentials, API keys (encrypted) + enabled BOOLEAN DEFAULT TRUE, + last_sync TIMESTAMP, + created_at TIMESTAMP DEFAULT NOW() +); + +-- Исходные данные (сырые) +CREATE TABLE raw_data ( + id BIGSERIAL PRIMARY KEY, + source_id UUID REFERENCES data_sources(id), + data JSONB NOT NULL, -- сырые данные из API + fetched_at TIMESTAMP NOT NULL, -- когда скачаны + processed BOOLEAN DEFAULT FALSE -- обработаны ETL +); + +-- Агрегированные данные (для дашборда) +CREATE TABLE metrics ( + id BIGSERIAL PRIMARY KEY, + client_id UUID REFERENCES clients(id), + metric_key VARCHAR(100) NOT NULL, -- revenue, profit, orders, etc. + metric_value DECIMAL(15,2) NOT NULL, + period_start DATE NOT NULL, + period_end DATE, + dimensions JSONB, -- city, channel, manager, etc. + source TEXT, -- откуда рассчитано + created_at TIMESTAMP DEFAULT NOW(), + UNIQUE(client_id, metric_key, period_start, dimensions::text) +); + +-- Индекс для быстрого поиска по дашборду +CREATE INDEX idx_metrics_client_period ON metrics(client_id, period_start DESC); +CREATE INDEX idx_metrics_key ON metrics(metric_key); + +-- История изменений дашборда (аудит) +CREATE TABLE dashboard_changes ( + id BIGSERIAL PRIMARY KEY, + client_id UUID REFERENCES clients(id), + metric_key VARCHAR(100), + old_value DECIMAL(15,2), + new_value DECIMAL(15,2), + change_pct DECIMAL(10,2), + changed_at TIMESTAMP DEFAULT NOW() +); + +-- Настройки дашборда (какие метрики показывать клиенту) +CREATE TABLE dashboard_config ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + client_id UUID REFERENCES clients(id) UNIQUE, + template VARCHAR(50), -- ecommerce, services, retails + metrics JSONB, -- какие метрики включены + refresh_interval INTEGER DEFAULT 1440, -- минут + created_at TIMESTAMP DEFAULT NOW() +); +``` + +## ETL Pipeline + +### Структура адаптера + +``` +roi24/PIPELINE/adapters/ +├── base.py # Базовый класс адаптера +├── 1c/ +│ ├── __init__.py +│ ├── xmlrpc.py # Подключение через XML-RPC 1С +│ ├── direct_db.py # Прямой доступ к БД 1С +│ └── exporters.py # Экспорт данных +├── bank/ +│ ├── __init__.py +│ ├── sberbank.py # СберБизнес +│ ├── tinkoff.py # Тинькофф +│ ├── tochka.py # Точка Банк +│ └── csv_import.py # Импорт из CSV +├── ad/ +│ ├── __init__.py +│ ├── yandex_direct.py # Яндекс.Директ API +│ └── vk_ads.py # VK Ads +├── crm/ +│ ├── __init__.py +│ ├── bitrix24.py # Битрикс24 REST API +│ └── amo.py # amoCRM API +└── marketplace/ + ├── __init__.py + └── ozon.py +``` + +### Базовый адаптер + +```python +# PIPELINE/adapters/base.py +from abc import ABC, abstractmethod +from datetime import datetime +from typing import Optional + +class BaseAdapter(ABC): + """Базовый класс для всех адаптеров источников данных.""" + + def __init__(self, config: dict): + self.config = config + self.last_sync: Optional[datetime] = None + + @abstractmethod + def fetch(self, date_from: str, date_to: str) -> list[dict]: + """Получить данные за период.""" + pass + + def _save_raw(self, data: list[dict], source_id: str): + """Сохранить сырые данные в PostgreSQL.""" + pass + + def _aggregate(self, raw: list[dict]) -> list[dict]: + """Преобразовать сырые данные в метрики.""" + pass + + def sync(self, date_from: str, date_to: str, source_id: str): + """Полный цикл синхронизации.""" + raw = self.fetch(date_from, date_to) + self._save_raw(raw, source_id) + metrics = self._aggregate(raw) + self.last_sync = datetime.now() + return metrics +``` + +### Типовой цикл ETL + +``` +1. APScheduler запускает job каждые N минут +2. Job для каждого источника данных: + a. Вызывает adapter.fetch(date_from, date_to) + b. Сохраняет сырые данные в raw_data + c. Агрегирует в метрики (metrics table) + d. Помечает raw_data как processed +3. При изменении агрегированных метрик > 10% — + записывает в dashboard_changes +``` + +## FastAPI API + +### Эндпоинты + +``` +GET /api/health # health-check +GET /api/dashboard/{client_id} # все метрики клиента +GET /api/metrics/{client_id}/{metric} # конкретная метрика +GET /api/trend/{client_id}/{metric} # тренд (сравнение периодов) +GET /api/export/{client_id}/{format} # экспорт в CSV/PDF +GET /api/clients # список клиентов +POST /api/clients/{id}/connect # подключить источник +DELETE /api/clients/{id}/sources/{src_id} # удалить источник +``` + +### Пример ответа + +```json +{ + "client_id": "uuid-here", + "generated_at": "2026-06-20T10:00:00Z", + "metrics": { + "revenue": { + "today": 125000, + "yesterday": 98000, + "week": 820000, + "month": 2450000, + "trend": "+12.5%", + "trend_direction": "up" + }, + "profit": { + "today": 38500, + "margin": "30.8%", + "trend": "+8.2%" + }, + "orders": { + "today": 47, + "conversion_rate": "3.2%", + "avg_check": 2660 + }, + "balance": { + "total": 1250000, + "debtor": 340000, + "creditor": 120000 + } + } +} +``` + +## Docker Compose (стартовый) + +```yaml +version: '3.9' + +services: + postgres: + image: postgres:16-alpine + environment: + POSTGRES_DB: roi24 + POSTGRES_USER: roi24 + POSTGRES_PASSWORD: change_me + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./storage/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql + + api: + build: + context: ./api + ports: + - "8000:8000" + environment: + DATABASE_URL: postgresql://roi24:change_me@postgres:5432/roi24 + depends_on: + - postgres + + scheduler: + build: + context: ./scripts + environment: + DATABASE_URL: postgresql://roi24:change_me@postgres:5432/roi24 + depends_on: + - postgres + command: ["python", "update_data.py"] + + nginx: + image: nginx:alpine + ports: + - "80:80" + volumes: + - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf + - ./dashboard:/usr/share/nginx/html + depends_on: + - api + +volumes: + postgres_data: +``` + +## Безопасность + +1. **Контент** credentials в `data_sources.config` — шифровать (AES-256) +2. **API** — JWT tokens для каждого клиента +3. **Данные** — изоляция между клиентами на уровне `client_id` +4. **SSL** — Nginx + Let's Encrypt (certbot) +5. **Бэкапы** — ежедневные бэкапы PostgreSQL (pg_dump) + +## Хостинг + +### Вариант для старта (один VPS) + +| Ресурс | Минимум | Рекомендуемый | +|--------|---------|--------------| +| CPU | 2 vCPU | 4 vCPU | +| RAM | 4 ГБ | 8 ГБ | +| SSD | 50 ГБ | 100 ГБ NVMe | +| Стоимость | ~1500₽/мес | ~3000₽/мес | + +**Recomended providers:** Selectel, Timeweb, Yandex Cloud + +### Этапы масштабирования + +1. **Этап 1 (1-10 клиентов):** Один VPS, всё в одном Docker Compose +2. **Этап 2 (10-50 клиентов):** Выделение PostgreSQL на отдельный сервер +3. **Этап 3 (50+ клиентов):** Kubernetes + автоскейлинг + Redis кэш diff --git a/README.md b/README.md index 22b23e7..368cbfa 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,166 @@ -# roi24 +# ROI24 — Дашборды для бизнеса +**Живые цифры бизнеса за 3 дня.** Подключаем 1С, банк, рекламу — и собственник видит выручку, маржу и кассу в реальном времени. + +--- + +## План проекта + +### Фаза 1: MVP (неделя 1-2) + +- [ ] **1.1. Архитектура** — выбрать стек, спроектировать pipeline данных + - Источники → Python-адаптер → PostgreSQL → FastAPI → HTML/ECharts + - Без ClickHouse на старте, без React +- [ ] **1.2. Техническая база** + - Настроить PostgreSQL на VPS + - Собрать базовый Docker-комPOSE (PostgreSQL + adminer) + - Спроектировать схему БД для типового клиента +- [ ] **1.3. Лендинг-презентация** + - Одностраничный лендинг с примерами дашбордов (фейковые но реалистичные данные) + - 5 сектов: hero → что это → примеры → как работает → CTA + - Деплой на Gitea Pages + +### Фаза 2: Первые клиенты (неделя 2-6) + +- [ ] **2.1. Outreach** — написать 20 знакомым предпринимателям +- [ ] **2.2. TenChat** — создать профиль, начать экспертный контент +- [ ] **2.3. Kwork / FL.ru** — разместить 2-3 предложения +- [ ] **2.4. Первый бесплатный проект** — кейс за фидбек +- [ ] **2.5. Сбор метрик** — фиксировать источники, метрики, проблемы, время внедрения + +### Фаза 3: Первый платный проект (неделя 4-8) + +- [ ] **3.1. Настройка pipeline** для реального клиента +- [ ] **3.2. Адаптер 1С** — парсинг через XML-RPC или прямой доступ к БД +- [ ] **3.3. Адаптер банка** — выгрузка CSV/API (СберБизнес, Тинькофф, Точка) +- [ ] **3.4. Адаптер рекламы** — Яндекс.Директ API, VK Ads +- [ ] **3.5. Дашборд** — 3-5 ключевых метрик в одном HTML +- [ ] **3.6. Автообновление** — cron-скрипт для обновления данных +- [ ] **3.7. Подписание договора + подписка** + +### Фаза 4: Масштабирование (неделя 8-16) + +- [ ] **4.1. Типизация клиентов** — 2-3 профиля (интернет-магазин, услуги, B2B) +- [ ] **4.2. Шаблоны дашбордов** — 3 готовых шаблона +- [ ] **4.3. Адаптер CRM** — Битрикс24 API, amoCRM +- [ ] **4.4. Система подписок** — разные тарифы, разная частота обновления +- [ ] **4.5. AI-фичи** — базовые прогнозы (линейная регрессия на выручку) +- [ ] **4.6. Партнёрство с 1С-интеграторами** + +### Фаза 5: Продукт (месяц 4-6+) + +- [ ] **5.1. SaaS-платформа** — мульти-тенантная архитектура +- [ ] **5.2. Self-service** — клиент сам подключает источники через веб-интерфейс +- [ ] **5.3. Дашборд-конструктор** — drag & drop для метрик +- [ ] **5.4. Telegram-уведомления** — алерты при отклонении метрик +- [ ] **5.5. Когортный анализ** — cohort analytics для e-commerce +- [ ] **5.6. Unit-экономика** — LTV, CAC, churn rate + +--- + +## Технический стек + +| Компонент | Инструмент | +|-----------|-----------| +| Бэкенд | Python 3.12 + FastAPI | +| База данных | PostgreSQL 16 | +| Визуализация | ECharts 5 / Chart.js | +| Контейнеризация | Docker + Docker Compose | +| Задачи | Celery + Redis / APScheduler | +| Деплой | VPS (Ubuntu 24.04) + Nginx | +| Фронтенд | HTML + JS (без фреймворков на старте) | +| CI/CD | Gitea Actions | + +## Источники данных (адаптеры) + +### Приоритет 1 (MVP) +- [ ] 1С:Предприятие 8.3 (XML-RPC или HTTP API) +- [ ] Банковские выписки (CSV/API: СберБизнес, Тинькофф, Точка) +- [ ] Яндекс.Директ API + +### Приоритет 2 (Фаза 4) +- [ ] amoCRM API +- [ ] Битрикс24 API +- [ ] Wildberries / Ozon API + +### Приоритет 3 (Фаза 5) +- [ ] RetailCRM +- [ ] СБИС / Контур.Экстерн +- [ ] Прямые API маркетплейсов + +## Ключевые метрики по нишам + +### Интернет-магазин +- Выручка (день/неделя/месяц) +- Маржинальная прибыль +- Конверсия в покупку +- Средний чек (AOV) +- LTV / CAC +- Динамика по каналам трафика + +### Услуги / B2B +- Pipeline (воронка продаж) +- Конверсия по этапам +- Дебиторская задолженность +- Загруженность команды +- Выручка по менеджерам + +### Розничная торговля +- Продажи по точкам +- Товарный запас +- Оборачиваемость +- Средний чек +- Трафик в зале + +## Ценообразование + +| Тариф | Внедрение | Подписка/мес | Что входит | +|-------|-----------|-------------|-----------| +| Старт | 50 000 ₽ | 10 000 ₽ | 1С + банк, 3 дашборда, 1 обновление/день | +| Бизнес | 100 000 ₽ | 25 000 ₽ | 1С + банк + CRM + реклама, 7 дашбордов, каждые 4ч | +| Под ключ | 200 000 ₽ | 50 000 ₽ | Все источники, кастомные метрики, AI-прогнозы, каждые 30мин | + +## KPI проекта + +| Метрика | Целевое значение | +|---------|-----------------| +| CAC (стоимость привлечения) | < 30 000 ₽ | +| LTV (пожизненная ценность) | > 300 000 ₽ (2 года подписки) | +| Churn rate | < 5% в месяц | +| Revenue per customer | > 25 000 ₽/мес | +| Время внедрения | < 3 рабочих дня | + +--- + +## Файлы проекта + +``` +roi24/ +├── README.md ← этот файл (план проекта) +├── ARCHITECTURE.md ← техническая архитектура +├── PIPELINE/ +│ ├── README.md +│ ├── 1c_adapter/ ← адаптер 1С +│ ├── bank_adapter/ ← адаптеры банков +│ ├── ad_adapter/ ← адаптеры рекламы +│ └── crm_adapter/ ← адаптеры CRM +├── storage/ +│ ├── schema.sql ← схема БД +│ └── migrations/ ← миграции +├── api/ +│ └── main.py ← FastAPI приложение +├── dashboard/ +│ ├── templates/ ← шаблоны дашбордов +│ │ ├── ecommerce.html +│ │ ├── services.html +│ │ └── retails.html +│ ├── static/ ← CSS, JS, images +│ └── utils/ ← helpers +├── landing/ ← лендинг-презентация +├── docker/ +│ ├── docker-compose.yml +│ └── nginx/ +└── scripts/ + ├── update_data.py ← cron-скрипт обновления + └── generate_report.py ← генерация PDF-отчётов +```