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>
14 KiB
14 KiB
Отчёт о реализации: Админ-панель, Модерация, Монетизация
Дата: 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)
Пользователи с ролями
| Пользователь | Роль | Пароль | |
|---|---|---|---|
| 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"} |
Инструкции по деплою
# На сервере 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
Верификация на проде
- Логин как
alice.chen@example.com(SUPER_ADMIN) → в хедере видна ссылка "Admin" /admin→ дашборд с 5 метриками/admin/users→ таблица юзеров с ролями и статусами/admin/users/:id→ детали юзера, бан david → логин как david → 403- Разбанить david → логин работает
/admin/settings→ отключить autoApprove- Создать листинг → статус PENDING_REVIEW
/admin/moderation→ approve → листинг активен- На странице товара → Report → модалка → отправить
/admin/reports→ resolve жалобу/admin/payments→ транзакции по типам/admin/settings→ изменить listing fee → проверить