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 }