Admin: per-user activity file (logins, logouts, orders) with CSV export
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
42
accounts/activity.py
Normal file
42
accounts/activity.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""
|
||||
«پروندهی کاربر»: ورود، خروج و خریدهای یک کاربر به ترتیبِ زمان، برای ادمین.
|
||||
|
||||
فقط میخواند؛ چیزی جدا ذخیره نمیکند، پس با جدولهای اصلی (LoginEvent، Order، StatusChangeLog) هرگز
|
||||
ناهماهنگ نمیشود. تصمیمِ ادغامنکردنِ اینها در یک جدول: ستونهایشان فرق دارد.
|
||||
آزموده نشده: کاربری با دهها هزار ردیف (همهی ردیفها در حافظه میآیند).
|
||||
"""
|
||||
from django.utils import timezone
|
||||
|
||||
from payment.models import Order
|
||||
from statuslog.models import StatusChangeLog
|
||||
|
||||
from .models import LoginEvent, User
|
||||
|
||||
_STATUS_FA = dict(Order.STATUS_CHOICES)
|
||||
_EVENT_FA = dict(LoginEvent.EVENT_CHOICES)
|
||||
COLUMNS = ['زمان', 'نوع', 'شرح', 'مبلغ', 'آیپی']
|
||||
|
||||
|
||||
def user_activity(user: User) -> list[dict]:
|
||||
rows = [{'at': user.created_at, 'kind': 'ثبتنام', 'detail': '', 'amount': '', 'ip': ''}]
|
||||
for e in LoginEvent.objects.filter(user_id=user.id):
|
||||
rows.append({'at': e.created_at, 'kind': _EVENT_FA.get(e.event, e.event),
|
||||
'detail': e.user_agent[:80], 'amount': '', 'ip': e.ip or ''})
|
||||
orders = list(Order.objects.filter(user_id=user.id))
|
||||
for o in orders:
|
||||
rows.append({
|
||||
'at': o.created_at, 'kind': 'سفارش',
|
||||
'detail': f'#{o.id} {o.plan_title or "بدون پلن"} ({o.get_provider_display()})',
|
||||
'amount': f'{o.amount} {o.currency}', 'ip': '',
|
||||
})
|
||||
for c in StatusChangeLog.objects.filter(label='payment.Order', object_id__in=[o.id for o in orders]):
|
||||
rows.append({
|
||||
'at': c.created_at, 'kind': 'تغییر وضعیت سفارش',
|
||||
'detail': f'#{c.object_id}: {_STATUS_FA.get(c.old_status, c.old_status or "—")} ← '
|
||||
f'{_STATUS_FA.get(c.new_status, c.new_status)} ({c.event})',
|
||||
'amount': '', 'ip': '',
|
||||
})
|
||||
rows.sort(key=lambda r: r['at'])
|
||||
for r in rows:
|
||||
r['at_local'] = timezone.localtime(r['at']).strftime('%Y-%m-%d %H:%M:%S')
|
||||
return rows
|
||||
Reference in New Issue
Block a user