Commit Graph

77 Commits

Author SHA1 Message Date
Fringg 6da61d7951 fix: убрать WITHDRAWAL из автонегации, добавить abs() в агрегации, исправить all_time_stats
- Убран WITHDRAWAL из автонегации в create_transaction (ломал profit,
  expenses и display flip в admin_users)
- Добавлен func.abs() в by_type агрегацию (transaction.py)
- Добавлен func.abs() в total_spent user.py (_build_spending_stats_select)
- Исправлен all_time_stats в боте и webapi: передаём явный диапазон дат
  вместо дефолтного текущего месяца
2026-03-05 09:05:02 +03:00
Fringg a7a18dd0d1 fix: устранение race condition при покупке устройств через re-lock после коммита
subtract_user_balance() делает внутренний коммит, что освобождает
SELECT FOR UPDATE блокировки. Добавлен паттерн re-lock + re-validate +
refund после вызова subtract_user_balance во всех 8 путях мутации
device_limit:

- cabinet: /devices, /devices/purchase, /devices/reduce
- miniapp: /subscription/devices
- bot handlers: execute_change_devices, confirm_add_devices
- auto-purchase: _auto_add_devices
- CRUD: add_subscription_devices

Также добавлен populate_existing=True ко всем SELECT FOR UPDATE запросам
для корректного обновления SQLAlchemy identity map.
2026-03-05 08:15:00 +03:00
Fringg e4a6aad621 fix: centralize has_had_paid_subscription into subtract_user_balance
Add mark_as_paid_subscription parameter to subtract_user_balance() that
atomically sets has_had_paid_subscription=True within the same FOR UPDATE
transaction as the balance deduction. This closes ALL purchase paths:

- Cabinet renew: add SELECT FOR UPDATE row lock (fix race condition),
  set has_had_paid_subscription atomically, remove standalone call
- Cabinet purchase_tariff: pass consume_promo_offer to subtract_user_balance
  (fix: inline clearing was wiped by db.refresh), remove standalone call
- Cabinet switch_tariff: add mark_as_paid_subscription=True
- Auto-extend: add mark_as_paid_subscription, remove standalone call
- Auto-purchase tariff: add consume_promo_offer + mark_as_paid_subscription
- Auto-purchase daily: add mark_as_paid_subscription
- Bot purchase/extend/trial handlers: add mark_as_paid_subscription
- All 8 tariff_purchase.py handlers: add mark_as_paid_subscription
- Both simple_subscription.py handlers: add mark_as_paid_subscription
- Menu smart activation: add mark_as_paid_subscription
- Monitoring autopay: add mark_as_paid_subscription
- Renewal service finalize: add mark_as_paid_subscription
- MiniApp purchase service: add mark_as_paid_subscription, remove standalone
- MiniApp renewal/tariff/switch: add mark_as_paid_subscription
2026-03-05 06:29:34 +03:00
Fringg 2664b4956d feat: account merge system — atomic user merge with full FK coverage
- Реализован execute_merge: атомарное слияние двух аккаунтов (primary поглощает secondary)
- Покрыты все 54 FK на users.id (38 таблиц): платежи, подписки, реферралы, тикеты, аудит
- Admin-actor FK (created_by, processed_by, admin_id, assigned_by, actor_user_id) — SET NULL
- User-ownership FK — переназначение на primary
- Dedup-then-reassign для таблиц с unique constraints
- Cross-referral deletion для ReferralEarning и ReferralContestEvent
- UserRole secondary удаляются (защита от эскалации привилегий)
- Merge token: Redis GETDEL (атомарное потребление), restore при ошибке
- Preview endpoint с rate limiting по IP
- Перенос баланса, email, telegram_id, OAuth провайдеров, партнёрского статуса
2026-03-05 05:23:39 +03:00
Fringg 18c2477173 feat: add referral code tracking to all cabinet auth methods + email_templates migration
Referral links from cabinet (?ref=CODE) were only tracked for email registration.
Now referral_code is accepted and processed in Telegram initData, Telegram Widget,
and OAuth authentication endpoints. Includes self-referral protection by email
for OAuth, proper error logging, and the missing email_templates table migration.
2026-02-18 23:59:29 +03:00
Fringg eb18994b7d fix: complete datetime.utcnow() → datetime.now(UTC) migration
- Migrate 660+ datetime.utcnow() across 153 files to datetime.now(UTC)
- Migrate 30+ datetime.now() without UTC to datetime.now(UTC)
- Convert all 170 DateTime columns to DateTime(timezone=True)
- Add migrate_datetime_to_timestamptz() in universal_migration with SET LOCAL timezone='UTC' safety
- Remove 70+ .replace(tzinfo=None) workarounds
- Fix utcfromtimestamp → fromtimestamp(..., tz=UTC)
- Fix fromtimestamp() without tz= (system_logs, backup_service, referral_diagnostics)
- Fix fromisoformat/isoparse to ensure aware output (platega, yookassa, wata, miniapp, nalogo)
- Fix strptime() to add .replace(tzinfo=UTC) (backup_service, referral_diagnostics)
- Fix datetime.combine() to include tzinfo=UTC (remnawave_sync, traffic_monitoring)
- Fix datetime.max/datetime.min sentinels with .replace(tzinfo=UTC)
- Rename panel_datetime_to_naive_utc → panel_datetime_to_utc
- Remove DTZ003 from ruff ignore list
2026-02-17 04:45:40 +03:00
Fringg a93a32f3a7 fix: resolve MissingGreenlet error when accessing subscription.tariff
Add .selectinload(Subscription.tariff) chain to all User queries that
load subscriptions, preventing lazy loading of the tariff relationship
in async context. Also replace unsafe getattr(subscription, 'tariff')
with explicit async get_tariff_by_id() in handle_extend_subscription.
2026-02-16 17:54:43 +03:00
Fringg 1f0fef114b refactor: complete structlog migration with contextvars, kwargs, and logging hardening
- Add ContextVarsMiddleware for automatic user_id/chat_id/username binding
  via structlog contextvars (aiogram) and http_method/http_path (FastAPI)
- Use bound_contextvars() context manager instead of clear_contextvars()
  to safely restore previous state instead of wiping all context
- Register ContextVarsMiddleware as outermost middleware (before GlobalError)
  so all error logs include user context
- Replace structlog.get_logger() with structlog.get_logger(__name__) across
  270 calls in 265 files for meaningful logger names
- Switch wrapper_class from BoundLogger to make_filtering_bound_logger()
  for pre-processor level filtering (performance optimization)
- Migrate 1411 %-style positional arg logger calls to structlog kwargs
  style across 161 files via AST script
- Migrate log_rotation_service.py from stdlib logging to structlog
- Add payment module prefixes to TelegramNotifierProcessor.IGNORED_LOGGER_PREFIXES
  and ExcludePaymentFilter.PAYMENT_MODULES to prevent payment data leaking
  to Telegram notifications and general log files
- Fix LoggingMiddleware: add from_user null-safety for channel posts,
  switch time.time() to time.monotonic() for duration measurement
- Remove duplicate logger assignments in purchase.py, config.py,
  inline.py, and admin/payments.py
2026-02-16 09:18:12 +03:00
Fringg c5124b97b6 fix: payment race conditions, balance atomicity, renewal rollback safety
- YooKassa: SELECT FOR UPDATE on payment row to prevent concurrent double-processing
- subtract_user_balance: row locking to prevent concurrent balance race conditions
- subtract_user_balance: transaction creation before commit for atomicity
- subscription renewal: compensating refund if extend_subscription fails after charge
- StaleDataError: use savepoint instead of full rollback to protect parent transaction
2026-02-11 21:49:37 +03:00
Ali Morshedzadeh 5482e609f8 Add initial Persian locale support and language handling updates 2026-02-09 16:53:50 +03:30
Fringg 41633af763 refactor: fix transaction boundaries, extract _finalize_oauth_login, replace deprecated datetime.utcnow 2026-02-07 02:35:55 +03:00
Fringg 97be4afbff feat: add OAuth 2.0 authorization (Google, Yandex, Discord, VK)
- Add OAuth provider config vars and helpers to config.py
- Add google_id, yandex_id, discord_id, vk_id columns to User model
- Create OAuth provider service with state management and 4 providers
- Add CRUD functions for OAuth user lookup, linking, and creation
- Add 3 API endpoints: providers list, authorize URL, callback
- Add alembic migration and universal_migration support
- Fix trial disable logic to cover OAuth auth_types
2026-02-07 01:58:55 +03:00
Egor d7e1b8fd5d Update user.py 2026-02-01 11:28:36 +03:00
Egor d611eecece Update user.py 2026-02-01 00:54:17 +03:00
Egor 9cc2a285dc Update user.py 2026-01-31 20:12:25 +03:00
Egor 25aba75413 Update user.py 2026-01-30 16:06:06 +03:00
Egor 6f40cdd09c Update user.py 2026-01-25 11:52:24 +03:00
Egor 3d9a8c39dc Update user.py 2026-01-24 09:51:13 +03:00
Egor b38e06383d Update user.py 2026-01-19 23:57:03 +03:00
PEDZEO 6b69ec750e feat: add cabinet (personal account) backend API
- Add JWT authentication for cabinet users
- Add Telegram WebApp authentication
- Add subscription management endpoints
- Add balance and transactions endpoints
- Add referral system endpoints
- Add tickets support for cabinet
- Add webhooks and websocket for real-time updates
- Add email verification service

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 23:20:20 +03:00
gy9vin 8e6082ce15 fix Черный список, мониторинг суточно графика по регламенту
Исправленные файлы:

  1. app/services/traffic_monitoring_service.py — удалены неиспользуемые импорты Decimal, aiohttp
  2. app/services/blacklist_service.py — удалён неиспользуемый импорт re
  3. app/database/crud/user.py:998 — создана отсутствующая функция get_users_with_active_subscriptions:
  async def get_users_with_active_subscriptions(db: AsyncSession) -> List[User]:
  3. Функция:
    - Возвращает пользователей с активными подписками
    - Фильтрует по remnawave_uuid IS NOT NULL (нужен для API Remnawave)
    - Проверяет end_date > now и status == ACTIVE
2025-12-30 23:11:54 +03:00
gy9vin 180cba4561 fix Расширение фильтров 2025-12-30 22:14:09 +03:00
gy9vin 54ffe3e126 feat(transactions): добавлен параметр payment_method для ручных пополнений баланса
Добавлена поддержка указания способа оплаты при пополнении баланса:

- add_user_balance(): новый параметр payment_method для передачи в транзакцию
- add_user_balance_by_id(): поддержка payment_method
- UserService: ручные пополнения админом пом
2025-12-26 08:53:08 +03:00
gy9vin 80785f22b0 Черный список, мониторинг суточно графика по регламенту 2025-12-10 19:13:52 +03:00
c0mrade c6c112fd17 refactor: improve logging level for balance subtraction debug info 2025-11-12 10:21:28 +03:00
Egor 7d7c5f3972 Update user.py 2025-11-05 18:51:35 +03:00
Egor c15b7a63fb Flush user before returning from create_user_no_commit 2025-11-05 18:19:22 +03:00
reshifter1 3201b60ff2 Merge branch 'dev4' into main 2025-11-04 22:57:38 +03:00
Pavel Stryuk 427011fe41 1) Отображение скидки на кнопках (красивое!)
2) У промогрупп появится приоритет
3) У пользователя может быть несколько промогрупп, но влиять будет только с наивысшим приоритетом
4) К промокодам можно будет добавить промогруппу. Все активировавшие промокод получат её
5) При выводе пользователей с промогруппой будет также выводиться ссылка на каждого. Можно будет отследить сливы промокодов "для своих". Я в целом это добавлю во все места, где пользователь выводится в админке
6) Исправить баг исчезновения триалки при пополнении
7) Исправить падающие тесты и добавить новых
8) Трафик: 0 ГБ в тестовой подписке исправить на Трафик: Безлимит
2025-11-04 13:05:02 +01:00
Egor 71c219e6ea Update user.py 2025-11-04 09:29:46 +03:00
Egor 06323f7168 Enhance search functionality for telegram_id
Added error handling for converting search input to int for telegram_id.
2025-11-04 07:39:12 +03:00
Mikhail 92cb1e3971 Merge branch 'Fr1ngg:main' into main 2025-11-02 15:08:01 +03:00
gy9vin 005fc95433 Массовая синхронизация пользователей с ремнем! 2025-11-02 15:07:28 +03:00
Egor 165691412b Clear referral edit state when returning to list 2025-11-01 01:58:08 +03:00
gy9vin f26df389b4 СРОЧНЫЙ ФИКС 2025-10-31 22:13:23 +03:00
Egor e592b3e5c4 Revert "Revert "Add poll management and delivery system"" 2025-10-23 06:03:41 +03:00
Egor 7b4cbb27b7 Revert "Add poll management and delivery system" 2025-10-23 05:37:40 +03:00
Egor 93554c7034 Add poll management and delivery system 2025-10-23 05:28:13 +03:00
Egor de57db14ea Delay first-topup flag until after referral processing 2025-10-11 08:25:11 +03:00
Egor 5d576bc727 Add expiration control for promo offer discounts 2025-10-05 17:01:11 +03:00
Egor 45586277ab fix: rollback session after promo log failures 2025-10-05 04:05:43 +03:00
Egor 6f67a36a58 Fix promo discount consumption and admin copy 2025-10-04 12:25:00 +03:00
Egor db9f91b336 Revert "Clear expired promo discounts when preparing checkout summaries" 2025-10-04 10:55:32 +03:00
Egor 0e0569fe23 Clear expired promo discounts before checkout 2025-10-04 10:53:09 +03:00
Egor b96d530808 Fix promo segment no subscription join 2025-10-04 10:13:45 +03:00
Egor e4c7a9cf15 Add admin promo offers and targeted discount workflows 2025-10-04 10:05:31 +03:00
Egor c4fa25321e Handle users sequence desync after backup restore 2025-10-03 23:35:47 +03:00
gy9vin c344f418c5 Расширение фильтров 2025-09-30 12:39:15 +03:00
Egor fb4d714441 Log admin balance deductions as transactions 2025-09-29 15:10:47 +03:00
PEDZEO c4b5db9002 fix(validation): sanitize имён + HTML-escape только в /start 2025-09-29 02:17:19 +03:00