from django import forms from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ from django.db import transaction, models from django.utils import timezone from university.models import ( Badge, UserExam, OnlineExam, UserOnlineExam, OnlineExamRegistrate, OnlineExamPromotionCode ) class ExamRegistrateForm(forms.Form): exam_time = forms.CharField(required=True) exam_venue = forms.CharField(required=True) def __init__(self, user, exam, *args, **kwargs): self.user = user self.exam = exam self.is_permitted = True self.required = [] return super(ExamRegistrateForm, self).__init__(*args, **kwargs) def clean_exam_time(self): exam_time = self.cleaned_data.get('exam_time') if exam_time and exam_time not in self.exam.exam_times: raise ValidationError(_('invalid exam time')) return exam_time def clean_exam_venue(self): exam_venue = self.cleaned_data.get('exam_venue') if exam_venue and exam_venue not in self.exam.venues: raise ValidationError(_('invalid exam venue')) return exam_venue def clean(self): if UserExam.objects.filter( user=self.user, exam=self.exam, status__in=(UserExam.STATUS_REGISTE_SUBMITTED, UserExam.STATUS_REGISTE_CONFIRMED) ).exists(): self.add_error('', _('already submitted for registration')) return missed_badges = set(self.exam.required_badges) \ - set(self.user.userbadge_set.values_list('id', flat=True)) if missed_badges: self.required = Badge.objects.filter(id__in=missed_badges)\ .values_list('description', flat=True) self.is_permitted = False if not (self.user.real_name and self.user.chinese_id_number and self.user.exam_contact_phone): self.add_error('user_info', _('incomplete exam information')) return self.cleaned_data def is_valid(self): if not super(ExamRegistrateForm, self).is_valid(): return False if not self.is_permitted: return False return True def save(self): UserExam.objects.create( user=self.user, exam=self.exam, exam_time=self.cleaned_data['exam_time'], exam_venue=self.cleaned_data['exam_venue']) class ExamEnrollForm(forms.Form): name = forms.CharField(required=True, max_length=64) chinese_id = forms.CharField(required=True, max_length=64) phone = forms.RegexField( required=True, regex=r'^1\d{10}$', error_messages={ 'invalid': _('invalid phone number'), 'required': _('phone number is required') }) email = forms.EmailField( required=True, error_messages={ 'required': _('email is required') }) company = forms.CharField(required=True, max_length=64) city = forms.CharField(required=True, max_length=64) tug_role = forms.CharField(required=True, max_length=64) exam_id = forms.IntegerField(required=True) payment_method = forms.IntegerField(required=True) promotion_code = forms.CharField(required=False, max_length=64) online_payment_success = forms.BooleanField(required=False) need_receipt = forms.BooleanField(required=False) receipt_header = forms.CharField(required=False, max_length=128) receipt_tin = forms.CharField(required=False, max_length=255) obtained_dba_certs = forms.CharField(required=False, max_length=255) def __init__(self, exam_flag, user, *args, **kwargs): self.exam_flag = exam_flag self.user = user self.online_exam = None self.promotion_code_instance = None return super(ExamEnrollForm, self).__init__(*args, **kwargs) def clean_chinese_id(self): chinese_id = self.cleaned_data.get('chinese_id') if chinese_id: # TODO if not (15 <= len(chinese_id) <= 18): raise ValidationError(_('invalid chinese ID number')) return chinese_id def clean_exam_id(self): exam_id = self.cleaned_data.get('exam_id') if exam_id: try: self.online_exam = OnlineExam.objects.get( flag=self.exam_flag, pk=exam_id) except Exception: raise ValidationError('所选考试不存在') if UserOnlineExam.objects.filter( online_exam=self.online_exam, user=self.user).exists(): raise ValidationError('已报名, 不可重复报名') if self.online_exam.registration_deadline <= timezone.now(): raise ValidationError('该场考试报名已截止,请选择其它场次') return exam_id def clean(self): if self._errors: return payment_method = self.cleaned_data.get('payment_method') promotion_code = self.cleaned_data.get('promotion_code') need_receipt = self.cleaned_data.get('need_receipt') receipt_header = self.cleaned_data.get('receipt_header') receipt_tin = self.cleaned_data.get('receipt_tin') if payment_method == 0: if not promotion_code: self.add_error('promotion_code', '请填写优惠码') return try: self.promotion_code_instance = OnlineExamPromotionCode.objects.get( code=promotion_code, flag=self.exam_flag, used=False ) if self.promotion_code_instance.code_type == OnlineExamPromotionCode.CODE_TYPE_PERSONAL: if self.exam_flag == 'PCTP' and self.promotion_code_instance.user != self.user: raise OnlineExamPromotionCode.DoesNotExist elif self.promotion_code_instance.code_type == OnlineExamPromotionCode.CODE_TYPE_GROUP: if self.promotion_code_instance.remain_times <= 0: raise OnlineExamPromotionCode.DoesNotExist except OnlineExamPromotionCode.DoesNotExist: self.add_error('promotion_code', '优惠码已被使用或不存在') return if need_receipt: if not receipt_header: self.add_error('receipt_header', '不能为空') if not receipt_tin: self.add_error('receipt_tin', '不能为空') return self.cleaned_data def save(self): with transaction.atomic(): registration = OnlineExamRegistrate.objects.create( flag=self.exam_flag, user=self.user, online_exam=self.online_exam, name=self.cleaned_data.get('name'), chinese_id=self.cleaned_data.get('chinese_id'), phone=self.cleaned_data.get('phone'), email=self.cleaned_data.get('email'), company=self.cleaned_data.get('company'), city=self.cleaned_data.get('city'), tug_role=self.cleaned_data.get('tug_role'), payment_method=self.cleaned_data.get('payment_method'), promotion_code=self.promotion_code_instance, need_receipt=self.cleaned_data.get('need_receipt', False), receipt_header=self.cleaned_data.get('receipt_header'), receipt_tin=self.cleaned_data.get('receipt_tin'), online_payment_success=self.cleaned_data.get('online_payment_success'), obtained_dba_certs=self.cleaned_data.get('obtained_dba_certs'), ) if self.promotion_code_instance: if self.promotion_code_instance.code_type == OnlineExamPromotionCode.CODE_TYPE_PERSONAL: self.promotion_code_instance.registration = registration self.promotion_code_instance.used = True self.promotion_code_instance.used_by = self.user self.promotion_code_instance.used_time = timezone.now() elif self.promotion_code_instance.code_type == OnlineExamPromotionCode.CODE_TYPE_GROUP: self.promotion_code_instance.remain_times = models.F('remain_times') - 1 self.promotion_code_instance.save() user_online_exam_status = UserOnlineExam.STATUS_REGISTERED else: user_online_exam_status = UserOnlineExam.STATUS_REGISTE_WAIT_CONFIRM UserOnlineExam.objects.create( user=self.user, online_exam=self.online_exam, status=user_online_exam_status, examinee_name=self.cleaned_data.get('name'), examinee_chinese_id=self.cleaned_data.get('chinese_id') ) class ExamEnrollUpdateForm(forms.Form): name = forms.CharField(required=True, max_length=64) chinese_id = forms.CharField(required=True, max_length=64) phone = forms.RegexField( required=True, regex=r'^1\d{10}$', error_messages={ 'invalid': _('invalid phone number'), 'required': _('phone number is required') }) email = forms.EmailField( required=True, error_messages={ 'required': _('email is required') }) company = forms.CharField(required=True, max_length=64) city = forms.CharField(required=True, max_length=64) tug_role = forms.CharField(required=True, max_length=64) exam_id = forms.IntegerField(required=True) obtained_dba_certs = forms.CharField(required=True, max_length=255) def __init__(self, user_online_exam, registration, *args, **kwargs): self.user_online_exam = user_online_exam self.registration = registration self.user = user_online_exam.user self.is_update_exam = False # 是否修改了考试场次 self.target_exam = None return super(ExamEnrollUpdateForm, self).__init__(*args, **kwargs) def clean_chinese_id(self): chinese_id = self.cleaned_data.get('chinese_id') if chinese_id: # TODO if not (15 <= len(chinese_id) <= 18): raise ValidationError(_('invalid chinese ID number')) return chinese_id def clean_exam_id(self): exam_id = self.cleaned_data.get('exam_id') if exam_id: try: self.target_exam = OnlineExam.objects.get( flag=self.user_online_exam.online_exam.flag, pk=exam_id) except Exception: raise ValidationError('所选考试不存在') if self.target_exam.id != self.registration.online_exam.id: self.is_update_exam = True if not self.registration.can_update_exam: raise ValidationError('本场考试开始前 3 天内不能再修改考试场次') if UserOnlineExam.objects.filter( online_exam=self.target_exam, user=self.user).exists(): raise ValidationError('已报名该场次, 请重新选择') if self.registration.exam_modification_remaining <= 0: raise ValidationError('无法修改, 已超出了最大修改次数') if self.target_exam.registration_deadline <= timezone.now(): raise ValidationError('该场考试报名已截止,请选择其它场次') return exam_id def clean(self): if self._errors: return if not self.registration.can_update_info_except_exam: raise ValidationError('考试已开始, 不允许修改报名信息') return self.cleaned_data def save(self): with transaction.atomic(): self.registration.name = self.cleaned_data.get('name') self.registration.chinese_id = self.cleaned_data.get('chinese_id') self.registration.phone = self.cleaned_data.get('phone') self.registration.email = self.cleaned_data.get('email') self.registration.company = self.cleaned_data.get('company') self.registration.city = self.cleaned_data.get('city') self.registration.tug_role = self.cleaned_data.get('tug_role') self.registration.obtained_dba_certs = self.cleaned_data.get('obtained_dba_certs') self.user_online_exam.examinee_name = self.registration.name self.user_online_exam.examinee_chinese_id = self.registration.chinese_id if self.is_update_exam: self.registration.online_exam = self.target_exam self.registration.exam_modified_times = models.F('exam_modified_times') + 1 self.user_online_exam.online_exam = self.target_exam self.user_online_exam.save(update_fields=[ 'online_exam', 'examinee_name', 'examinee_chinese_id']) self.registration.save() return self.target_exam