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:
NW
2026-08-09 00:22:22 +01:00
parent 338a700b3a
commit d7680357af
13 changed files with 517 additions and 1192 deletions

220
docs/DATABASE.md Normal file
View 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/` (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-схема админки должна отражать ту же структуру