admin_users_personels
This commit is contained in:
@@ -497,6 +497,7 @@ async def list_users(
|
||||
role: Optional[str] = Query(None, description="Szerepkör szűrés (pl. admin, user)"),
|
||||
is_active: Optional[bool] = Query(None, description="Aktív státusz szűrés"),
|
||||
is_deleted: Optional[bool] = Query(None, description="Törölt státusz szűrés"),
|
||||
plan_filter: Optional[str] = Query(None, description="Csomag szűrés (pl. FREE, PREMIUM, ENTERPRISE)"),
|
||||
db: AsyncSession = Depends(deps.get_db),
|
||||
current_user: User = Depends(deps.get_current_active_user),
|
||||
_ = Depends(deps.RequirePermission("user:view")),
|
||||
@@ -580,8 +581,10 @@ async def list_users(
|
||||
)
|
||||
|
||||
if role:
|
||||
# Case-insensitive role matching
|
||||
role_upper = role.upper()
|
||||
try:
|
||||
role_enum = UserRole(role)
|
||||
role_enum = UserRole(role_upper)
|
||||
query = query.where(User.role == role_enum)
|
||||
except ValueError:
|
||||
raise HTTPException(
|
||||
@@ -592,6 +595,8 @@ async def list_users(
|
||||
query = query.where(User.is_active == is_active)
|
||||
if is_deleted is not None:
|
||||
query = query.where(User.is_deleted == is_deleted)
|
||||
if plan_filter:
|
||||
query = query.where(User.subscription_plan == plan_filter.upper())
|
||||
|
||||
count_query = select(func.count()).select_from(query.subquery())
|
||||
total_result = await db.execute(count_query)
|
||||
@@ -625,6 +630,12 @@ async def list_users(
|
||||
parts.append(str(address.house_number))
|
||||
address_str = ', '.join(parts) if parts else None
|
||||
|
||||
# Személy nevének összefűzése
|
||||
person_name = None
|
||||
if person:
|
||||
parts = [p for p in [person.last_name, person.first_name] if p]
|
||||
person_name = ' '.join(parts) if parts else None
|
||||
|
||||
user_list.append({
|
||||
"id": u.id,
|
||||
"email": u.email,
|
||||
@@ -637,6 +648,7 @@ async def list_users(
|
||||
"created_at": u.created_at.isoformat() if u.created_at else None,
|
||||
"deleted_at": u.deleted_at.isoformat() if u.deleted_at else None,
|
||||
# Person adatok
|
||||
"person_name": person_name,
|
||||
"first_name": person.first_name if person else None,
|
||||
"last_name": person.last_name if person else None,
|
||||
"phone": person.phone if person else None,
|
||||
@@ -656,6 +668,148 @@ async def list_users(
|
||||
}
|
||||
|
||||
|
||||
@router.get("/users/stats", tags=["User Management"])
|
||||
async def get_user_stats(
|
||||
db: AsyncSession = Depends(deps.get_db),
|
||||
current_user: User = Depends(deps.get_current_active_user),
|
||||
_ = Depends(deps.RequirePermission("user:view")),
|
||||
):
|
||||
"""
|
||||
Felhasználói statisztikák a Dashboard számára.
|
||||
|
||||
Visszaadja az összesítő adatokat: teljes, aktív, törölt, kitiltott felhasználók,
|
||||
mai/héti/havi új regisztrációk, szerepkör és előfizetés szerinti megoszlás,
|
||||
nyelvi statisztikák, Person kapcsolatok, szervezeti adatok.
|
||||
"""
|
||||
from datetime import date, timedelta
|
||||
|
||||
today_start = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
week_start = today_start - timedelta(days=today_start.weekday())
|
||||
month_start = today_start.replace(day=1)
|
||||
|
||||
# === ALAP STATISZTIKÁK ===
|
||||
total_result = await db.execute(select(func.count(User.id)))
|
||||
total_users = total_result.scalar() or 0
|
||||
|
||||
active_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.is_active == True, User.is_deleted == False)
|
||||
)
|
||||
active_users = active_result.scalar() or 0
|
||||
|
||||
deleted_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.is_deleted == True)
|
||||
)
|
||||
deleted_users = deleted_result.scalar() or 0
|
||||
|
||||
# Banned = is_active=False AND is_deleted=False (deactivated but not deleted)
|
||||
banned_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.is_active == False, User.is_deleted == False)
|
||||
)
|
||||
banned_users = banned_result.scalar() or 0
|
||||
|
||||
# === ÚJ REGISZTRÁCIÓK ===
|
||||
new_today_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.created_at >= today_start)
|
||||
)
|
||||
new_users_today = new_today_result.scalar() or 0
|
||||
|
||||
new_week_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.created_at >= week_start)
|
||||
)
|
||||
new_users_this_week = new_week_result.scalar() or 0
|
||||
|
||||
new_month_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.created_at >= month_start)
|
||||
)
|
||||
new_users_this_month = new_month_result.scalar() or 0
|
||||
|
||||
# === SZEREPKÖR SZERINTI MEGOSZLÁS ===
|
||||
role_result = await db.execute(
|
||||
select(User.role, func.count(User.id)).group_by(User.role)
|
||||
)
|
||||
users_by_role = {}
|
||||
for row in role_result:
|
||||
role_key = row[0].value if hasattr(row[0], "value") else str(row[0])
|
||||
users_by_role[role_key] = row[1]
|
||||
|
||||
# === ELŐFIZETÉS SZERINTI MEGOSZLÁS ===
|
||||
plan_result = await db.execute(
|
||||
select(User.subscription_plan, func.count(User.id)).group_by(User.subscription_plan)
|
||||
)
|
||||
users_by_plan = {row[0]: row[1] for row in plan_result}
|
||||
|
||||
# === NYELV SZERINTI MEGOSZLÁS ===
|
||||
lang_result = await db.execute(
|
||||
select(User.preferred_language, func.count(User.id)).group_by(User.preferred_language)
|
||||
)
|
||||
users_by_language = {row[0]: row[1] for row in lang_result}
|
||||
|
||||
# === PERSON KAPCSOLATOK ===
|
||||
with_person_result = await db.execute(
|
||||
select(func.count(User.id)).where(User.person_id.isnot(None))
|
||||
)
|
||||
users_with_person = with_person_result.scalar() or 0
|
||||
|
||||
users_without_person = total_users - users_with_person
|
||||
|
||||
# === SZERVEZETI STATISZTIKÁK ===
|
||||
from app.models.marketplace.organization import Organization, OrganizationMember
|
||||
|
||||
org_count_result = await db.execute(
|
||||
select(func.count(Organization.id)).where(Organization.is_deleted == False)
|
||||
)
|
||||
active_organizations_count = org_count_result.scalar() or 0
|
||||
|
||||
memberships_result = await db.execute(
|
||||
select(func.count(OrganizationMember.id))
|
||||
)
|
||||
total_memberships = memberships_result.scalar() or 0
|
||||
|
||||
# === JÁRMŰ STATISZTIKÁK ===
|
||||
from app.models.vehicle.asset import Asset
|
||||
|
||||
vehicle_count_result = await db.execute(
|
||||
select(func.count(Asset.id))
|
||||
)
|
||||
total_vehicles = vehicle_count_result.scalar() or 0
|
||||
|
||||
# === REGISZTRÁCIÓS TREND (utolsó 30 nap) ===
|
||||
thirty_days_ago = today_start - timedelta(days=30)
|
||||
trend_result = await db.execute(
|
||||
text("""
|
||||
SELECT DATE(created_at) as reg_date, COUNT(*) as cnt
|
||||
FROM identity.users
|
||||
WHERE created_at >= :start_date
|
||||
GROUP BY DATE(created_at)
|
||||
ORDER BY reg_date
|
||||
"""),
|
||||
{"start_date": thirty_days_ago}
|
||||
)
|
||||
registration_trend = [
|
||||
{"date": row[0].isoformat() if hasattr(row[0], 'isoformat') else str(row[0]), "count": row[1]}
|
||||
for row in trend_result
|
||||
]
|
||||
|
||||
return {
|
||||
"total_users": total_users,
|
||||
"active_users": active_users,
|
||||
"deleted_users": deleted_users,
|
||||
"banned_users": banned_users,
|
||||
"new_users_today": new_users_today,
|
||||
"new_users_this_week": new_users_this_week,
|
||||
"new_users_this_month": new_users_this_month,
|
||||
"users_by_role": users_by_role,
|
||||
"users_by_plan": users_by_plan,
|
||||
"users_by_language": users_by_language,
|
||||
"users_with_person": users_with_person,
|
||||
"users_without_person": users_without_person,
|
||||
"total_vehicles": total_vehicles,
|
||||
"active_organizations_count": active_organizations_count,
|
||||
"total_memberships": total_memberships,
|
||||
"registration_trend": registration_trend,
|
||||
}
|
||||
|
||||
|
||||
@router.post("/users/bulk-action", tags=["User Management"])
|
||||
async def bulk_user_action(
|
||||
request: BulkActionRequest,
|
||||
@@ -732,11 +886,11 @@ async def bulk_user_action(
|
||||
affected_count += 1
|
||||
|
||||
audit_log = SecurityAuditLog(
|
||||
user_id=current_user.id,
|
||||
actor_id=current_user.id,
|
||||
action=f"bulk_{request.action}",
|
||||
details=f"Bulk action '{request.action}' on {affected_count} users. IDs: {request.user_ids}",
|
||||
payload_before={},
|
||||
payload_after={"details": f"Bulk action '{request.action}' on {affected_count} users. IDs: {request.user_ids}"},
|
||||
is_critical=(request.action in ("hard_delete", "ban")),
|
||||
ip_address="admin_api"
|
||||
)
|
||||
db.add(audit_log)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user