You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

201 lines
7.8 KiB

from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils import timezone
from apps.transaction.models import TransactionParticipant
from apps.course.models import Participant
from apps.account.models import User
class Command(BaseCommand):
help = 'بررسی تراکنش‌های موفق و ایجاد شرکت‌کنندگان دوره در صورت عدم وجود'
def add_arguments(self, parser):
parser.add_argument(
'--dry-run',
action='store_true',
help='فقط نمایش تراکنش‌هایی که نیاز به بروزرسانی دارند بدون اعمال تغییرات',
)
parser.add_argument(
'--transaction-id',
type=int,
help='بررسی تراکنش خاص با ID مشخص',
)
parser.add_argument(
'--user-email',
type=str,
help='بررسی تراکنش‌های کاربر خاص',
)
parser.add_argument(
'--course-slug',
type=str,
help='بررسی تراکنش‌های دوره خاص',
)
def handle(self, *args, **options):
dry_run = options['dry_run']
transaction_id = options.get('transaction_id')
user_email = options.get('user_email')
course_slug = options.get('course_slug')
# ساخت queryset اولیه
queryset = TransactionParticipant.objects.filter(
status=TransactionParticipant.TransactionStatus.SUCCESS,
is_deleted=False
).select_related('user', 'course')
# اعمال فیلترهای اضافی
if transaction_id:
queryset = queryset.filter(id=transaction_id)
if user_email:
try:
user = User.objects.get(email=user_email)
queryset = queryset.filter(user=user)
except User.DoesNotExist:
raise CommandError(f'کاربر با ایمیل {user_email} یافت نشد.')
if course_slug:
queryset = queryset.filter(course__slug=course_slug)
total_transactions = queryset.count()
if total_transactions == 0:
self.stdout.write(
self.style.WARNING('هیچ تراکنش موفقی برای بررسی یافت نشد.')
)
return
self.stdout.write(
self.style.SUCCESS(f'تعداد {total_transactions} تراکنش موفق برای بررسی یافت شد.')
)
missing_participants = []
existing_participants = []
errors = []
# بررسی هر تراکنش
for trans in queryset:
try:
# بررسی وجود participant
participant_exists = Participant.objects.filter(
student=trans.user,
course=trans.course
).exists()
if not participant_exists:
missing_participants.append(trans)
self.stdout.write(
self.style.WARNING(
f'❌ تراکنش {trans.id}: کاربر {trans.user.email} در دوره "{trans.course.title}" ثبت‌نام نشده'
)
)
else:
existing_participants.append(trans)
self.stdout.write(
self.style.SUCCESS(
f'✅ تراکنش {trans.id}: کاربر {trans.user.email} در دوره "{trans.course.title}" قبلاً ثبت‌نام شده'
)
)
except Exception as e:
errors.append((trans, str(e)))
self.stdout.write(
self.style.ERROR(
f'⚠️ خطا در بررسی تراکنش {trans.id}: {str(e)}'
)
)
# نمایش خلاصه
self.stdout.write('\n' + '='*50)
self.stdout.write(f'📊 خلاصه نتایج:')
self.stdout.write(f' • کل تراکنش‌های بررسی شده: {total_transactions}')
self.stdout.write(f' • شرکت‌کنندگان موجود: {len(existing_participants)}')
self.stdout.write(f' • شرکت‌کنندگان ناموجود: {len(missing_participants)}')
self.stdout.write(f' • خطاها: {len(errors)}')
self.stdout.write('='*50 + '\n')
if not missing_participants:
self.stdout.write(
self.style.SUCCESS('🎉 همه تراکنش‌های موفق دارای شرکت‌کننده مربوطه هستند!')
)
return
if dry_run:
self.stdout.write(
self.style.WARNING(
f'🔍 حالت Dry Run: {len(missing_participants)} شرکت‌کننده نیاز به ایجاد دارند.'
)
)
self.stdout.write(
'برای اعمال تغییرات، دستور را بدون --dry-run اجرا کنید.'
)
return
# ایجاد شرکت‌کنندگان ناموجود
created_count = 0
failed_count = 0
self.stdout.write(
self.style.SUCCESS(f'🚀 شروع ایجاد {len(missing_participants)} شرکت‌کننده...')
)
for trans in missing_participants:
try:
with transaction.atomic():
# اضافه کردن نقش student اگر وجود نداشته باشد
if not trans.user.has_role('student'):
trans.user.add_role('student')
self.stdout.write(
f' 👤 نقش student به کاربر {trans.user.email} اضافه شد'
)
# ایجاد participant
participant = Participant.objects.create(
student=trans.user,
course=trans.course
)
created_count += 1
self.stdout.write(
self.style.SUCCESS(
f' ✅ شرکت‌کننده ایجاد شد: {trans.user.email} در دوره "{trans.course.title}"'
)
)
except Exception as e:
failed_count += 1
self.stdout.write(
self.style.ERROR(
f' ❌ خطا در ایجاد شرکت‌کننده برای تراکنش {trans.id}: {str(e)}'
)
)
# نمایش نتیجه نهایی
self.stdout.write('\n' + '='*50)
self.stdout.write('🏁 نتیجه نهایی:')
self.stdout.write(f' • شرکت‌کنندگان ایجاد شده: {created_count}')
self.stdout.write(f' • شکست‌ها: {failed_count}')
if created_count > 0:
self.stdout.write(
self.style.SUCCESS(f'✅ {created_count} شرکت‌کننده با موفقیت ایجاد شد!')
)
if failed_count > 0:
self.stdout.write(
self.style.ERROR(f'❌ {failed_count} مورد با خطا مواجه شد!')
)
self.stdout.write('='*50)
def get_transaction_info(self, trans):
"""اطلاعات کامل تراکنش را برمی‌گرداند"""
return {
'id': trans.id,
'user_email': trans.user.email,
'course_title': trans.course.title,
'course_slug': trans.course.slug,
'price': trans.price,
'created_at': trans.created_at,
'status': trans.status
}