250 lines
		
	
	
		
			No EOL
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			No EOL
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from django import forms
 | 
						||
from django.contrib.auth import get_user_model
 | 
						||
from django.contrib.auth.forms import UserCreationForm
 | 
						||
from .models import Profile, Role
 | 
						||
from common.consts import UserRoles, USER_TYPE_CHOICES
 | 
						||
 | 
						||
User = get_user_model()
 | 
						||
 | 
						||
class CustomerForm(forms.ModelForm):
 | 
						||
    """فرم برای افزودن مشترک جدید"""
 | 
						||
    first_name = forms.CharField(
 | 
						||
        max_length=150,
 | 
						||
        label="نام",
 | 
						||
        widget=forms.TextInput(attrs={
 | 
						||
            'class': 'form-control',
 | 
						||
            'placeholder': 'نام'
 | 
						||
        })
 | 
						||
    )
 | 
						||
    last_name = forms.CharField(
 | 
						||
        max_length=150,
 | 
						||
        label="نام خانوادگی",
 | 
						||
        widget=forms.TextInput(attrs={
 | 
						||
            'class': 'form-control',
 | 
						||
            'placeholder': 'نام خانوادگی'
 | 
						||
        })
 | 
						||
    )
 | 
						||
    
 | 
						||
    class Meta:
 | 
						||
        model = Profile
 | 
						||
        fields = [
 | 
						||
            'user_type', 'phone_number_1', 'phone_number_2', 'national_code', 
 | 
						||
            'company_name', 'company_national_id',
 | 
						||
            'address', 'card_number', 'account_number', 'bank_name'
 | 
						||
        ]
 | 
						||
        widgets = {
 | 
						||
            'user_type': forms.Select(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'id': 'user-type-select'
 | 
						||
            }),
 | 
						||
            'phone_number_1': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': '09123456789',
 | 
						||
                'required': True
 | 
						||
            }),
 | 
						||
            'phone_number_2': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': '02112345678'
 | 
						||
            }),
 | 
						||
            'national_code': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': '1234567890',
 | 
						||
                'maxlength': '10',
 | 
						||
                'required': 'required'
 | 
						||
            }),
 | 
						||
            'company_name': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control company-field',
 | 
						||
                'placeholder': 'نام شرکت'
 | 
						||
            }),
 | 
						||
            'company_national_id': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control company-field',
 | 
						||
                'placeholder': 'شناسه ملی شرکت',
 | 
						||
                'maxlength': '11'
 | 
						||
            }),
 | 
						||
            'address': forms.Textarea(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': 'آدرس کامل',
 | 
						||
                'rows': '3',
 | 
						||
                'required': True
 | 
						||
            }),
 | 
						||
            'card_number': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': 'شماره کارت بانکی',
 | 
						||
                'maxlength': '16',
 | 
						||
                'required': True
 | 
						||
            }),
 | 
						||
            'account_number': forms.TextInput(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': 'شماره حساب بانکی',
 | 
						||
                'maxlength': '20',
 | 
						||
                'required': True
 | 
						||
            }),
 | 
						||
            'bank_name': forms.Select(attrs={
 | 
						||
                'class': 'form-control',
 | 
						||
                'placeholder': 'نام بانک',
 | 
						||
                'required': True
 | 
						||
            }),
 | 
						||
        }
 | 
						||
        labels = {
 | 
						||
            'user_type': 'نوع کاربر',
 | 
						||
            'phone_number_1': 'تلفن ۱',
 | 
						||
            'phone_number_2': 'تلفن ۲',
 | 
						||
            'national_code': 'کد ملی',
 | 
						||
            'company_name': 'نام شرکت',
 | 
						||
            'company_national_id': 'شناسه ملی شرکت',
 | 
						||
            'address': 'آدرس',
 | 
						||
            'card_number': 'شماره کارت',
 | 
						||
            'account_number': 'شماره حساب',
 | 
						||
            'bank_name': 'نام بانک',
 | 
						||
        }
 | 
						||
 | 
						||
    def clean_national_code(self):
 | 
						||
        national_code = self.cleaned_data.get('national_code')
 | 
						||
        if national_code:
 | 
						||
            # Check if user with this national code exists
 | 
						||
            existing_user = User.objects.filter(username=national_code).first()
 | 
						||
            if existing_user:
 | 
						||
                # If we're editing and the user is the same, it's OK
 | 
						||
                if self.instance and self.instance.user and existing_user == self.instance.user:
 | 
						||
                    return national_code
 | 
						||
                # Otherwise, it's a duplicate
 | 
						||
                raise forms.ValidationError('این کد ملی قبلاً استفاده شده است.')
 | 
						||
        return national_code
 | 
						||
 | 
						||
    def clean(self):
 | 
						||
        cleaned_data = super().clean()
 | 
						||
        user_type = cleaned_data.get('user_type')
 | 
						||
        company_name = cleaned_data.get('company_name')
 | 
						||
        company_national_id = cleaned_data.get('company_national_id')
 | 
						||
        
 | 
						||
        # If user type is legal, company fields are required
 | 
						||
        if user_type == 'legal':
 | 
						||
            if not company_name:
 | 
						||
                self.add_error('company_name', 'برای کاربران حقوقی نام شرکت الزامی است.')
 | 
						||
            if not company_national_id:
 | 
						||
                self.add_error('company_national_id', 'برای کاربران حقوقی شناسه ملی شرکت الزامی است.')
 | 
						||
        
 | 
						||
        return cleaned_data
 | 
						||
 | 
						||
    def save(self, commit=True):
 | 
						||
        def _compute_completed(cleaned):
 | 
						||
            try:
 | 
						||
                first_ok = bool((cleaned.get('first_name') or '').strip())
 | 
						||
                last_ok = bool((cleaned.get('last_name') or '').strip())
 | 
						||
                nc_ok = bool((cleaned.get('national_code') or '').strip())
 | 
						||
                phone_ok = bool((cleaned.get('phone_number_1') or '').strip() or (cleaned.get('phone_number_2') or '').strip())
 | 
						||
                addr_ok = bool((cleaned.get('address') or '').strip())
 | 
						||
                bank_ok = bool(cleaned.get('bank_name'))
 | 
						||
                card_ok = bool((cleaned.get('card_number') or '').strip())
 | 
						||
                acc_ok = bool((cleaned.get('account_number') or '').strip())
 | 
						||
                
 | 
						||
                # Check user type specific requirements
 | 
						||
                user_type = cleaned.get('user_type', 'individual')
 | 
						||
                if user_type == 'legal':
 | 
						||
                    company_name_ok = bool((cleaned.get('company_name') or '').strip())
 | 
						||
                    company_id_ok = bool((cleaned.get('company_national_id') or '').strip())
 | 
						||
                    return all([first_ok, last_ok, nc_ok, phone_ok, addr_ok, bank_ok, card_ok, acc_ok, company_name_ok, company_id_ok])
 | 
						||
                else:
 | 
						||
                    return all([first_ok, last_ok, nc_ok, phone_ok, addr_ok, bank_ok, card_ok, acc_ok])
 | 
						||
            except Exception:
 | 
						||
                return False
 | 
						||
        # Check if this is an update (instance exists)
 | 
						||
        if self.instance and self.instance.pk:
 | 
						||
            # Update existing profile
 | 
						||
            profile = super().save(commit=False)
 | 
						||
            
 | 
						||
            # Update user information
 | 
						||
            user = profile.user
 | 
						||
            user.first_name = self.cleaned_data['first_name']
 | 
						||
            user.last_name = self.cleaned_data['last_name']
 | 
						||
            user.save()
 | 
						||
            
 | 
						||
            # Set affairs, county, and broker from current user's profile
 | 
						||
            if hasattr(self, 'request') and self.request.user.is_authenticated:
 | 
						||
                current_user_profile = getattr(self.request.user, 'profile', None)
 | 
						||
                if current_user_profile:
 | 
						||
                    profile.affairs = current_user_profile.affairs
 | 
						||
                    profile.county = current_user_profile.county
 | 
						||
                    profile.broker = current_user_profile.broker
 | 
						||
            # Set completion flag based on provided form data
 | 
						||
            profile.is_completed = _compute_completed({
 | 
						||
                'first_name': user.first_name,
 | 
						||
                'last_name': user.last_name,
 | 
						||
                'user_type': self.cleaned_data.get('user_type'),
 | 
						||
                'national_code': self.cleaned_data.get('national_code'),
 | 
						||
                'phone_number_1': self.cleaned_data.get('phone_number_1'),
 | 
						||
                'phone_number_2': self.cleaned_data.get('phone_number_2'),
 | 
						||
                'company_name': self.cleaned_data.get('company_name'),
 | 
						||
                'company_national_id': self.cleaned_data.get('company_national_id'),
 | 
						||
                'address': self.cleaned_data.get('address'),
 | 
						||
                'bank_name': self.cleaned_data.get('bank_name'),
 | 
						||
                'card_number': self.cleaned_data.get('card_number'),
 | 
						||
                'account_number': self.cleaned_data.get('account_number'),
 | 
						||
            })
 | 
						||
            
 | 
						||
            if commit:
 | 
						||
                profile.save()
 | 
						||
                self.save_m2m()
 | 
						||
            
 | 
						||
            return profile
 | 
						||
        else:
 | 
						||
            # Create new profile
 | 
						||
            # Get national code as username
 | 
						||
            national_code = self.cleaned_data.get('national_code')
 | 
						||
            if not national_code:
 | 
						||
                raise forms.ValidationError('کد ملی الزامی است.')
 | 
						||
            
 | 
						||
            # Create User with default password
 | 
						||
            user = User.objects.create_user(
 | 
						||
                username=national_code,
 | 
						||
                email='',  # Empty email
 | 
						||
                password='sooha1234',  # Default password
 | 
						||
                first_name=self.cleaned_data['first_name'],
 | 
						||
                last_name=self.cleaned_data['last_name']
 | 
						||
            )
 | 
						||
            
 | 
						||
            # Create Profile
 | 
						||
            profile = super().save(commit=False)
 | 
						||
            profile.user = user
 | 
						||
            profile.owner = user
 | 
						||
            
 | 
						||
            # Set affairs, county, and broker from current user's profile
 | 
						||
            if hasattr(self, 'request') and self.request.user.is_authenticated:
 | 
						||
                current_user_profile = getattr(self.request.user, 'profile', None)
 | 
						||
                if current_user_profile:
 | 
						||
                    profile.affairs = current_user_profile.affairs
 | 
						||
                    profile.county = current_user_profile.county
 | 
						||
                    profile.broker = current_user_profile.broker
 | 
						||
            # Set completion flag based on provided form data
 | 
						||
            profile.is_completed = _compute_completed({
 | 
						||
                'first_name': user.first_name,
 | 
						||
                'last_name': user.last_name,
 | 
						||
                'user_type': self.cleaned_data.get('user_type'),
 | 
						||
                'national_code': self.cleaned_data.get('national_code'),
 | 
						||
                'phone_number_1': self.cleaned_data.get('phone_number_1'),
 | 
						||
                'phone_number_2': self.cleaned_data.get('phone_number_2'),
 | 
						||
                'company_name': self.cleaned_data.get('company_name'),
 | 
						||
                'company_national_id': self.cleaned_data.get('company_national_id'),
 | 
						||
                'address': self.cleaned_data.get('address'),
 | 
						||
                'bank_name': self.cleaned_data.get('bank_name'),
 | 
						||
                'card_number': self.cleaned_data.get('card_number'),
 | 
						||
                'account_number': self.cleaned_data.get('account_number'),
 | 
						||
            })
 | 
						||
            
 | 
						||
            if commit:
 | 
						||
                profile.save()
 | 
						||
                self.save_m2m()
 | 
						||
                
 | 
						||
                # Add customer role after profile is saved
 | 
						||
                customer_role = Role.objects.filter(slug=UserRoles.CUSTOMER.value).first()
 | 
						||
                if customer_role:
 | 
						||
                    profile.roles.add(customer_role)
 | 
						||
                else:
 | 
						||
                    # Create customer role if it doesn't exist
 | 
						||
                    customer_role = Role.objects.create(
 | 
						||
                        name='مشترک',
 | 
						||
                        slug=UserRoles.CUSTOMER.value
 | 
						||
                    )
 | 
						||
                    profile.roles.add(customer_role)
 | 
						||
            
 | 
						||
            return profile  |