Files
telegram-shop/docs/DATABASE.md
NW d7680357af chore: repo cleanup + docs for admin API and DB schema (v1.2.8)
- remove stale docs/admin-frontend-spec.md (old Express/EJS admin), unused templates/ (SmartAdmin copy), dead scripts/sync-agents.cjs, committed dev.pid
- add docs/API.md (admin REST API reference) and docs/DATABASE.md (DB schema)
- refresh .env.example: drop stale ADMIN_PORT/SHOP_CONTAINER, add ADMIN_URL, HEALTH_PORT, DEFAULT_LANGUAGE, CHATBOT_API_*
- add npm run lint so Gitea workflows pass
- rebrand web-testing suite from APAW to telegram-shop
2026-08-09 00:22:22 +01:00

221 lines
7.3 KiB
Markdown
Raw Permalink 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.
# Telegram Shop — Database Schema
Единая SQLite-база (`db/shop.db`), используемая **одновременно** ботом (`src/`, better-sqlite3) и админ-панелью (`admin-next/`, Prisma). Источник истины схемы: `admin-next/prisma/schema.prisma`.
Миграции бота: `src/migrations/` (001014, runner: `src/migrations/runner.js`).
## Схема
### users — пользователи Telegram
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| telegram_id | TEXT UNIQUE | ID в Telegram |
| username | TEXT? | |
| country / city / district | TEXT? | География |
| status | INTEGER (0) | 0=active, 2=blocked |
| total_balance | REAL (0) | Основной баланс |
| bonus_balance | REAL (0) | Бонусный баланс |
| language | TEXT ('en') | en / es / de |
| language_set | INTEGER (0) | Флаг выбора языка |
| notes | TEXT? | Заметки админа (миграция 014) |
| created_at | DATETIME | |
Связи: `wallets`, `transactions`, `purchases`.
### crypto_wallets — криптокошельки
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| user_id | INTEGER FK → users | |
| wallet_type | TEXT | BTC / LTC / ETH / USDT / USDC |
| address | TEXT | |
| derivation_path | TEXT? | |
| mnemonic | TEXT? | Seed-фраза (зашифрована) |
| balance | REAL (0) | |
| created_at | DATETIME | |
Уникальность: `(user_id, wallet_type)` — один кошелёк каждого типа на пользователя.
### transactions — транзакции
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| user_id | INTEGER FK → users | |
| wallet_type | TEXT | |
| tx_hash | TEXT? | |
| amount | REAL | |
| created_at | DATETIME | |
### locations — локации
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| country | TEXT | |
| city | TEXT | |
| district | TEXT ('') | |
| is_active | INTEGER (1) | 0/1 |
| created_at | DATETIME | |
Уникальность: `(country, city, district)`.
### categories — категории
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| location_id | INTEGER FK → locations | |
| name | TEXT | |
| is_active | INTEGER (1) | |
| created_at | DATETIME | |
Уникальность: `(location_id, name)`.
### subcategories — подкатегории
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| category_id | INTEGER FK → categories | |
| name | TEXT | |
| is_active | INTEGER (1) | |
| created_at | DATETIME | |
Уникальность: `(category_id, name)`.
### products — товары
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| location_id | INTEGER FK → locations | |
| category_id | INTEGER FK → categories | |
| subcategory_id | INTEGER? FK → subcategories | |
| name | TEXT | |
| description | TEXT? | |
| private_data | TEXT? | Скрытый контент (выдаётся после покупки) |
| price | REAL | |
| quantity_in_stock | INTEGER (0) | Для mono-товаров = 999999 |
| photo_url | TEXT? | Публичное фото |
| hidden_photo_url | TEXT? | Скрытое фото |
| hidden_coordinates | TEXT? | Скрытые координаты |
| hidden_description | TEXT? | Скрытое описание |
| is_mono | INTEGER (0) | 1 = неограниченный товар |
| created_at | DATETIME | |
### purchases — покупки
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| user_id | INTEGER FK → users | |
| product_id | INTEGER FK → products | |
| wallet_type | TEXT? | |
| tx_hash | TEXT? | |
| quantity | INTEGER | |
| total_price | REAL | |
| purchase_date | DATETIME | |
| status | TEXT ('pending') | pending / completed / cancelled |
### commission_payments — комиссионные выплаты
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| total_balance_usd | REAL | |
| commission_rate | REAL | |
| commission_amount_usd | REAL | |
| paid_amount_usd | REAL | |
| wallet_count | INTEGER | |
| note | TEXT? | |
| created_at | DATETIME | |
### audit_log — журнал аудита
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| action | TEXT | `balance_adjust`, `operator_connect`, `seed_phrase_viewed`, `clear_all` и др. |
| admin_id | TEXT | Роль или telegram_id |
| details | TEXT? | JSON-строка с контекстом |
| created_at | DATETIME | |
### chat_sessions — чат-сессии (чатбот)
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| session_id | TEXT UNIQUE | |
| telegram_id | TEXT? | |
| lead_id | INTEGER? FK → leads | |
| messages | TEXT | JSON-массив `{role, content, timestamp}` |
| language | TEXT ('en') | |
| device / ip / country | TEXT? | |
| customer_profile | TEXT? | AI-профиль клиента (JSON) |
| is_active | BOOLEAN (true) | |
| operator_name | TEXT? | |
| auto_reply_disabled | BOOLEAN (false) | |
| operator_connected_at | DATETIME? | |
| created_at / updated_at | DATETIME | |
### leads — лиды
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| telegram_id | TEXT? UNIQUE | |
| name / phone / email / telegram | TEXT? | |
| status | TEXT ('new') | new / contacted / qualified / lost / spam |
| verification | TEXT ('pending') | |
| notes | TEXT? | |
| custom_fields | TEXT ('{}') | JSON |
| geo_address | TEXT? | |
| ai_lead_score | REAL? | |
| created_at / updated_at | DATETIME | |
Связь: `chatSessions`.
### site_settings — настройки (ключ-значение)
| Колонка | Тип | Описание |
|---|---|---|
| id | INTEGER PK | |
| key | TEXT UNIQUE | Например `chatbot_*` |
| value | TEXT | |
| created_at / updated_at | DATETIME | |
### user_states — состояния пользователей бота
| Колонка | Тип | Описание |
|---|---|---|
| chat_id | TEXT PK | |
| state_data | TEXT? | JSON состояния |
| updated_at | INTEGER | Unix-время |
## Связи (ER-сводка)
```
users 1──N crypto_wallets
users 1──N transactions
users 1──N purchases
locations 1──N categories 1──N subcategories
locations 1──N products
categories 1──N products
subcategories 1──N products
products 1──N purchases
leads 1──N chat_sessions
leads 1──1 users (по telegram_id, не FK)
```
## Примечания
- **Бот и админка работают с одной БД**: любые изменения мгновенно видны обеим сторонам
- `users` и `leads`**отдельные таблицы**, связываются по `telegram_id` (не внешний ключ)
- `mnemonic` хранится зашифрованным (ключ `ENCRYPTION_KEY`)
- Каскадное удаление: wallets/transactions/purchases удаляются вместе с пользователем; products — вместе с location/category
- Миграции бота нумеруются `NNN_*.js`; Prisma-схема админки должна отражать ту же структуру