Full rental marketplace with 6 categories (apartment, house, car, motorcycle, bicycle, ebike). Booking workflow: create → confirm → pay → active → complete → payout. Landlord dashboard, admin moderation, availability calendar, Stripe Connect payouts. 14 QA bugs found and fixed including validator schemas, API response types, HTTP methods. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
320 lines
14 KiB
Markdown
320 lines
14 KiB
Markdown
# Отчёт о реализации: Админ-панель, Модерация, Монетизация
|
||
|
||
**Дата**: 22 февраля 2026
|
||
**Проект**: Marketplace
|
||
**Статус**: Реализовано, собрано, мигрировано, seed обновлён
|
||
|
||
---
|
||
|
||
## Общий объём работ
|
||
|
||
- **29 новых файлов** создано
|
||
- **13 существующих файлов** модифицировано
|
||
- **42 файла** затронуто суммарно
|
||
- **1 новая зависимость** (`recharts`) установлена
|
||
- **1 миграция БД** применена (`admin_moderation_monetization`)
|
||
|
||
---
|
||
|
||
## Новые серверные файлы (16)
|
||
|
||
| # | Файл | Назначение | Статус |
|
||
|---|---|---|---|
|
||
| 1 | `server/src/middleware/requireRole.ts` | RBAC middleware — `requireModerator`, `requireAdmin`, `requireSuperAdmin` | Готово |
|
||
| 2 | `server/src/middleware/checkBanned.ts` | Проверка бана пользователя (403) | Готово |
|
||
| 3 | `server/src/utils/moderation.ts` | Кэш PlatformConfig (60с), проверка blockedKeywords | Готово |
|
||
| 4 | `server/src/routes/admin/index.ts` | Агрегатор всех админ-роутов с authenticate | Готово |
|
||
| 5 | `server/src/routes/admin/stats.ts` | GET /api/admin/stats — дашборд-аналитика | Готово |
|
||
| 6 | `server/src/routes/admin/users.ts` | CRUD юзеров, бан/разбан, смена ролей | Готово |
|
||
| 7 | `server/src/routes/admin/listings.ts` | Approve/reject листингов, featured, force delete | Готово |
|
||
| 8 | `server/src/routes/admin/reports.ts` | Управление жалобами — список, детали, resolve/dismiss | Готово |
|
||
| 9 | `server/src/routes/admin/moderation.ts` | Очередь PENDING_REVIEW + лог модерации | Готово |
|
||
| 10 | `server/src/routes/admin/payments.ts` | Все платежи + revenue breakdown по типам | Готово |
|
||
| 11 | `server/src/routes/admin/settings.ts` | CRUD PlatformConfig с инвалидацией кэша | Готово |
|
||
| 12 | `server/src/routes/report.ts` | POST /api/reports — создание жалобы юзером | Готово |
|
||
| 13 | `server/src/routes/subscription.ts` | Подписки: current, create, cancel | Готово |
|
||
| 14 | `server/src/routes/promotion.ts` | Продвижение листингов: promote, get status | Готово |
|
||
| 15 | `server/src/validators/admin.ts` | Zod-схемы: ban, role, reject, resolve, settings | Готово |
|
||
| 16 | `server/src/validators/report.ts` | Zod-схема создания жалобы | Готово |
|
||
|
||
---
|
||
|
||
## Новые клиентские файлы (13)
|
||
|
||
| # | Файл | Назначение | Статус |
|
||
|---|---|---|---|
|
||
| 17 | `client/src/components/layout/RequireRole.tsx` | Route guard по роли пользователя | Готово |
|
||
| 18 | `client/src/components/layout/AdminLayout.tsx` | Sidebar-layout админки с навигацией | Готово |
|
||
| 19 | `client/src/components/ui/StatCard.tsx` | Карточка метрики (иконка, число, цвет) | Готово |
|
||
| 20 | `client/src/components/ui/DataTable.tsx` | Переиспользуемая таблица с поиском и пагинацией | Готово |
|
||
| 21 | `client/src/components/ReportModal.tsx` | Модалка жалобы с радиокнопками причин | Готово |
|
||
| 22 | `client/src/pages/admin/AdminDashboardPage.tsx` | Дашборд: 5 метрик + Quick Stats + Health | Готово |
|
||
| 23 | `client/src/pages/admin/AdminUsersPage.tsx` | Таблица юзеров с поиском и навигацией | Готово |
|
||
| 24 | `client/src/pages/admin/AdminUserDetailPage.tsx` | Детали юзера: профиль, статы, бан, роль, история | Готово |
|
||
| 25 | `client/src/pages/admin/AdminListingsPage.tsx` | Таблица листингов с табами по статусу | Готово |
|
||
| 26 | `client/src/pages/admin/AdminReportsPage.tsx` | Жалобы с табами + модалка resolve/dismiss | Готово |
|
||
| 27 | `client/src/pages/admin/AdminModerationPage.tsx` | Очередь модерации — карточки с approve/reject | Готово |
|
||
| 28 | `client/src/pages/admin/AdminPaymentsPage.tsx` | 4 StatCard выручки + таблица транзакций | Готово |
|
||
| 29 | `client/src/pages/admin/AdminSettingsPage.tsx` | Форма настроек: fees, limits, moderation | Готово |
|
||
|
||
---
|
||
|
||
## Модифицированные файлы (13)
|
||
|
||
| # | Файл | Что изменено | Статус |
|
||
|---|---|---|---|
|
||
| 30 | `server/prisma/schema.prisma` | 8 новых enum, 6 новых моделей, 3 модели расширены | Готово |
|
||
| 31 | `server/prisma/seed.ts` | + PlatformConfig, + роли (alice=SA, bob=A, carol=M), + cleanup новых таблиц | Готово |
|
||
| 32 | `server/src/index.ts` | + 4 новых route group: reports, subscriptions, promotions, admin | Готово |
|
||
| 33 | `server/src/middleware/auth.ts` | + `userRole?: string` в Request type | Готово |
|
||
| 34 | `server/src/routes/auth.ts` | + `role` в select (3 места), + проверка `isBanned` при логине | Готово |
|
||
| 35 | `server/src/routes/listing.ts` | + autoApprove check, + blockedKeywords check, + isFeatured в select | Готово |
|
||
| 36 | `server/src/routes/payment.ts` | + динамический listingFee из PlatformConfig, + type: LISTING_FEE | Готово |
|
||
| 37 | `server/src/routes/offer.ts` | + создание Commission payment при ACCEPTED | Готово |
|
||
| 38 | `client/src/types/index.ts` | + role в User, + PENDING_REVIEW, + новые NotificationType, + 5 новых интерфейсов | Готово |
|
||
| 39 | `client/src/context/AuthContext.tsx` | + isAdmin, isModerator, isSuperAdmin | Готово |
|
||
| 40 | `client/src/router.tsx` | + /admin/* routes (8 маршрутов) | Готово |
|
||
| 41 | `client/src/components/layout/Header.tsx` | + ссылка "Admin" с иконкой Shield | Готово |
|
||
| 42 | `client/src/pages/ProductDetailPage.tsx` | + ReportModal вместо alert() | Готово |
|
||
| + | `client/src/pages/NotificationsPage.tsx` | + иконки и цвета для 6 новых NotificationType | Готово |
|
||
|
||
---
|
||
|
||
## Схема БД — новые enum'ы
|
||
|
||
```
|
||
UserRole: USER | MODERATOR | ADMIN | SUPER_ADMIN
|
||
ReportReason: SPAM | INAPPROPRIATE | SCAM | COUNTERFEIT | PROHIBITED_ITEM | HARASSMENT | OTHER
|
||
ReportStatus: OPEN | REVIEWING | RESOLVED | DISMISSED
|
||
ReportTargetType: LISTING | USER
|
||
SubscriptionTier: BASIC | PRO | BUSINESS
|
||
SubscriptionStatus: ACTIVE | CANCELLED | EXPIRED | PAST_DUE
|
||
PaymentType: LISTING_FEE | COMMISSION | PROMOTION | SUBSCRIPTION
|
||
ModerationAction: APPROVED | REJECTED | WARNING | BAN | UNBAN | LISTING_DELETED | LISTING_FEATURED
|
||
```
|
||
|
||
---
|
||
|
||
## Схема БД — новые модели
|
||
|
||
### Report
|
||
```
|
||
id, reporterId → User, targetType (LISTING|USER), targetId, reason, description?,
|
||
status (OPEN→REVIEWING→RESOLVED|DISMISSED), resolvedBy?, resolution?
|
||
```
|
||
|
||
### PlatformConfig (singleton)
|
||
```
|
||
listingFee ($5), commissionPercent (5%), autoApprove (true),
|
||
maxImagesPerListing (6), maxListingsFreeTier (5),
|
||
proPrice ($9.99), businessPrice ($29.99), promotionDayPrice ($2.99),
|
||
blockedKeywords []
|
||
```
|
||
|
||
### Subscription
|
||
```
|
||
userId (unique) → User, tier (BASIC|PRO|BUSINESS), status,
|
||
stripeSubscriptionId?, currentPeriodEnd?
|
||
```
|
||
|
||
### PromotedListing
|
||
```
|
||
listingId (unique) → Listing, userId → User, startDate, endDate,
|
||
amountPaid, isActive
|
||
```
|
||
|
||
### ModerationLog
|
||
```
|
||
moderatorId → User, targetUserId?, targetListingId?,
|
||
action (ModerationAction), reason?, details (Json?)
|
||
```
|
||
|
||
---
|
||
|
||
## API Endpoints — полный список
|
||
|
||
### Admin Stats
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/stats` | MODERATOR+ |
|
||
| GET | `/api/admin/stats/revenue` | ADMIN+ |
|
||
| GET | `/api/admin/stats/users` | ADMIN+ |
|
||
| GET | `/api/admin/stats/listings` | MODERATOR+ |
|
||
|
||
### Admin Users
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/users` | MODERATOR+ |
|
||
| GET | `/api/admin/users/:id` | MODERATOR+ |
|
||
| PATCH | `/api/admin/users/:id/role` | SUPER_ADMIN |
|
||
| POST | `/api/admin/users/:id/ban` | ADMIN+ |
|
||
| POST | `/api/admin/users/:id/unban` | ADMIN+ |
|
||
|
||
### Admin Listings
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/listings` | MODERATOR+ |
|
||
| POST | `/api/admin/listings/:id/approve` | MODERATOR+ |
|
||
| POST | `/api/admin/listings/:id/reject` | MODERATOR+ |
|
||
| DELETE | `/api/admin/listings/:id` | ADMIN+ |
|
||
| POST | `/api/admin/listings/:id/feature` | ADMIN+ |
|
||
|
||
### Admin Reports
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/reports` | MODERATOR+ |
|
||
| GET | `/api/admin/reports/:id` | MODERATOR+ |
|
||
| PATCH | `/api/admin/reports/:id` | MODERATOR+ |
|
||
|
||
### Admin Moderation
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/moderation/queue` | MODERATOR+ |
|
||
| GET | `/api/admin/moderation/logs` | ADMIN+ |
|
||
|
||
### Admin Payments
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/payments` | ADMIN+ |
|
||
| GET | `/api/admin/payments/revenue` | ADMIN+ |
|
||
|
||
### Admin Settings
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/admin/settings` | ADMIN+ |
|
||
| PATCH | `/api/admin/settings` | SUPER_ADMIN |
|
||
|
||
### User Reports
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| POST | `/api/reports` | Авторизованный |
|
||
|
||
### Subscriptions
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| GET | `/api/subscriptions/current` | Авторизованный |
|
||
| POST | `/api/subscriptions/create` | Авторизованный |
|
||
| POST | `/api/subscriptions/cancel` | Авторизованный |
|
||
|
||
### Promotions
|
||
| Method | Path | Доступ |
|
||
|---|---|---|
|
||
| POST | `/api/listings/:id/promote` | Авторизованный |
|
||
| GET | `/api/listings/:id/promotion` | Авторизованный |
|
||
|
||
---
|
||
|
||
## Роли и права
|
||
|
||
| Действие | USER | MODERATOR | ADMIN | SUPER_ADMIN |
|
||
|---|---|---|---|---|
|
||
| Просмотр дашборда | - | + | + | + |
|
||
| Просмотр юзеров | - | + | + | + |
|
||
| Бан/разбан | - | - | + | + |
|
||
| Смена роли | - | - | - | + |
|
||
| Approve/Reject листинг | - | + | + | + |
|
||
| Force delete листинг | - | - | + | + |
|
||
| Feature листинг | - | - | + | + |
|
||
| Управление жалобами | - | + | + | + |
|
||
| Просмотр платежей | - | - | + | + |
|
||
| Настройки платформы (чтение) | - | - | + | + |
|
||
| Настройки платформы (запись) | - | - | - | + |
|
||
| Создание жалобы | + | + | + | + |
|
||
| Подписки | + | + | + | + |
|
||
| Продвижение | + | + | + | + |
|
||
|
||
---
|
||
|
||
## Тестовые данные (seed)
|
||
|
||
### Пользователи с ролями
|
||
| Пользователь | Email | Роль | Пароль |
|
||
|---|---|---|---|
|
||
| Alice Chen | alice.chen@example.com | SUPER_ADMIN | password123 |
|
||
| Bob Martinez | bob.martinez@example.com | ADMIN | password123 |
|
||
| Carol Nguyen | carol.nguyen@example.com | MODERATOR | password123 |
|
||
| David Kim | david.kim@example.com | USER | password123 |
|
||
| Eva Johnson | eva.johnson@example.com | USER | password123 |
|
||
|
||
### PlatformConfig (дефолты)
|
||
- Listing Fee: $5.00
|
||
- Commission: 5%
|
||
- Auto-Approve: true (включено)
|
||
- Max Images: 6
|
||
- Free Tier Limit: 5 листингов
|
||
- Pro Price: $9.99/мес
|
||
- Business Price: $29.99/мес
|
||
- Promotion Day Price: $2.99
|
||
- Blocked Keywords: `illegal`, `drugs`, `weapons`
|
||
|
||
---
|
||
|
||
## Миграция данных — обратная совместимость
|
||
|
||
| Поле | Default | Влияние на старые данные |
|
||
|---|---|---|
|
||
| `User.role` | `USER` | Все существующие юзеры → USER |
|
||
| `User.isBanned` | `false` | Никто не затронут |
|
||
| `ListingStatus.PENDING_REVIEW` | — | Аддитивно, старые данные не ломаются |
|
||
| `Payment.type` | `LISTING_FEE` | Корректно для всех существующих платежей |
|
||
| `PlatformConfig.autoApprove` | `true` | Текущее поведение не меняется |
|
||
|
||
---
|
||
|
||
## Проверка сборки
|
||
|
||
| Проверка | Результат |
|
||
|---|---|
|
||
| `npx tsc --noEmit` (server) | Без ошибок |
|
||
| `npx tsc --noEmit` (client) | Без ошибок |
|
||
| `npm run build --workspace=client` | Успешно (432 KB JS, 47 KB CSS) |
|
||
| `npx prisma migrate dev` | Миграция применена |
|
||
| `npx tsx prisma/seed.ts` | Seed выполнен |
|
||
| Health check `/api/health` | `{"status":"ok"}` |
|
||
|
||
---
|
||
|
||
## Инструкции по деплою
|
||
|
||
```bash
|
||
# На сервере 173.212.212.157:
|
||
|
||
# 1. Обновить код
|
||
cd /var/www/marketplace-app && git pull
|
||
|
||
# 2. Установить зависимости
|
||
npm install
|
||
|
||
# 3. Применить миграцию
|
||
cd server && npx prisma db push
|
||
|
||
# 4. Обновить seed (опционально)
|
||
npx tsx prisma/seed.ts
|
||
|
||
# 5. Собрать клиент
|
||
cd .. && npm run build --workspace=client
|
||
|
||
# 6. Скопировать билд
|
||
cp -r client/dist/* /var/www/marketplace/
|
||
|
||
# 7. Перезапустить сервер
|
||
pm2 restart marketplace-api
|
||
```
|
||
|
||
---
|
||
|
||
## Верификация на проде
|
||
|
||
1. Логин как `alice.chen@example.com` (SUPER_ADMIN) → в хедере видна ссылка "Admin"
|
||
2. `/admin` → дашборд с 5 метриками
|
||
3. `/admin/users` → таблица юзеров с ролями и статусами
|
||
4. `/admin/users/:id` → детали юзера, бан david → логин как david → 403
|
||
5. Разбанить david → логин работает
|
||
6. `/admin/settings` → отключить autoApprove
|
||
7. Создать листинг → статус PENDING_REVIEW
|
||
8. `/admin/moderation` → approve → листинг активен
|
||
9. На странице товара → Report → модалка → отправить
|
||
10. `/admin/reports` → resolve жалобу
|
||
11. `/admin/payments` → транзакции по типам
|
||
12. `/admin/settings` → изменить listing fee → проверить
|