Recalculate primary promo group instead of forcing target

This commit is contained in:
Egor
2025-11-05 17:35:09 +03:00
parent d88f13784a
commit 8730a68b40
2 changed files with 58 additions and 2 deletions

View File

@@ -1,5 +1,6 @@
"""CRUD операции для связи пользователей с промогруппами (Many-to-Many)."""
import logging
from datetime import datetime
from typing import List, Optional
from sqlalchemy import select, and_, desc
@@ -11,6 +12,48 @@ from app.database.models import UserPromoGroup, PromoGroup, User
logger = logging.getLogger(__name__)
async def _sync_user_primary_promo_group(
db: AsyncSession,
user_id: int,
) -> None:
"""Синхронизирует колонку users.promo_group_id с primary промогруппой."""
try:
result = await db.execute(
select(UserPromoGroup.promo_group_id)
.join(PromoGroup, UserPromoGroup.promo_group_id == PromoGroup.id)
.where(UserPromoGroup.user_id == user_id)
.order_by(desc(PromoGroup.priority), PromoGroup.id)
)
first = result.first()
new_primary_id = first[0] if first else None
user = await db.get(User, user_id)
if not user:
return
if user.promo_group_id != new_primary_id:
user.promo_group_id = new_primary_id
user.updated_at = datetime.utcnow()
except Exception as error:
logger.error(
"Ошибка синхронизации primary промогруппы пользователя %s: %s",
user_id,
error,
)
async def sync_user_primary_promo_group(
db: AsyncSession,
user_id: int,
) -> None:
"""Публичная обертка для синхронизации primary промогруппы пользователя."""
await _sync_user_primary_promo_group(db, user_id)
async def add_user_to_promo_group(
db: AsyncSession,
user_id: int,
@@ -40,9 +83,13 @@ async def add_user_to_promo_group(
user_promo_group = UserPromoGroup(
user_id=user_id,
promo_group_id=promo_group_id,
assigned_by=assigned_by
assigned_by=assigned_by,
)
db.add(user_promo_group)
await db.flush()
await _sync_user_primary_promo_group(db, user_id)
await db.commit()
await db.refresh(user_promo_group)
@@ -87,6 +134,10 @@ async def remove_user_from_promo_group(
return False
await db.delete(user_promo_group)
await db.flush()
await _sync_user_primary_promo_group(db, user_id)
await db.commit()
logger.info(f"У пользователя {user_id} удалена промогруппа {promo_group_id}")

View File

@@ -92,7 +92,11 @@ async def maybe_assign_promo_group_by_total_spent(
db: AsyncSession,
user_id: int,
) -> Optional[PromoGroup]:
from app.database.crud.user_promo_group import add_user_to_promo_group, has_user_promo_group
from app.database.crud.user_promo_group import (
add_user_to_promo_group,
has_user_promo_group,
sync_user_primary_promo_group,
)
user = await db.get(User, user_id)
if not user:
@@ -138,6 +142,7 @@ async def maybe_assign_promo_group_by_total_spent(
user.telegram_id,
target_group.name,
)
await sync_user_primary_promo_group(db, user_id)
if target_threshold > previous_threshold:
user.auto_promo_group_threshold_kopeks = target_threshold
user.updated_at = datetime.utcnow()