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
This commit is contained in:
220
docs/DATABASE.md
Normal file
220
docs/DATABASE.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# Telegram Shop — Database Schema
|
||||
|
||||
Единая SQLite-база (`db/shop.db`), используемая **одновременно** ботом (`src/`, better-sqlite3) и админ-панелью (`admin-next/`, Prisma). Источник истины схемы: `admin-next/prisma/schema.prisma`.
|
||||
|
||||
Миграции бота: `src/migrations/` (001–014, 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-схема админки должна отражать ту же структуру
|
||||
Reference in New Issue
Block a user