SillaAMP_V2/B_main/forms.py

311 lines
13 KiB
Python
Raw Normal View History

import re
from django import forms
from django.contrib.auth.models import User
from .models import Person
from .peopleinfo import PEOPLE
def format_phone_number(phone):
"""전화번호에서 대시 제거"""
return re.sub(r'[^0-9]', '', phone)
def format_phone_with_dash(phone):
"""전화번호에 대시 추가 (010-1234-5678 형식)"""
phone = format_phone_number(phone)
if len(phone) == 11:
return f"{phone[:3]}-{phone[3:7]}-{phone[7:]}"
return phone
# peopleinfo.py에서 PEOPLE 데이터를 가져와서 허가된 사람들의 정보로 변환
ALLOWED_PEOPLE = []
for person in PEOPLE:
# 전화번호에서 대시 제거
phone_without_dash = format_phone_number(person['연락처'])
ALLOWED_PEOPLE.append({
'이름': person['이름'],
'연락처': phone_without_dash
})
def is_allowed_person(name, phone):
"""허가된 사람인지 확인"""
formatted_phone = format_phone_number(phone)
for person in ALLOWED_PEOPLE:
if person['이름'] == name and person['연락처'] == formatted_phone:
return True
return False
def is_already_registered(name, phone):
"""이미 가입한 사용자인지 확인"""
# 전화번호 포맷팅 적용
formatted_phone = format_phone_number(phone)
# 전화번호로 User 검색 (username이 전화번호이므로)
existing_user = User.objects.filter(username=formatted_phone).first()
if existing_user:
# 해당 User와 연결된 Person이 있는 경우 (이미 회원가입한 상태)
try:
person = Person.objects.get(user=existing_user)
return True
except Person.DoesNotExist:
pass
# 이름과 전화번호로 Person 검색 (user가 있는 경우만 - 이미 회원가입한 상태)
if Person.objects.filter(
이름=name,
연락처=formatted_phone,
user__isnull=False
).exists():
return True
return False
def get_allowed_names():
"""허가된 모든 이름 목록 반환"""
return [person['이름'] for person in ALLOWED_PEOPLE]
def get_phone_by_name(name):
"""이름으로 전화번호 찾기"""
for person in ALLOWED_PEOPLE:
if person['이름'] == name:
return person['연락처']
return None
class CustomFileInput(forms.FileInput):
""""Currently:" 텍스트를 제거하는 커스텀 파일 입력 위젯"""
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
# "Currently:" 텍스트 제거
if 'help_text' in context:
context['help_text'] = ''
return context
class Step1PhoneForm(forms.Form):
name = forms.CharField(
max_length=50,
label='이름',
widget=forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': '이름'
})
)
phone = forms.CharField(
max_length=11,
label='전화번호',
widget=forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': '01012345678'
})
)
verification_code = forms.CharField(
max_length=6,
label='인증번호',
required=False,
widget=forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': '6자리 인증번호'
})
)
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')
phone = cleaned_data.get('phone')
if name and phone:
# 전화번호 포맷팅 적용 (대시 제거)
formatted_phone = format_phone_number(phone)
cleaned_data['phone'] = formatted_phone
# 이미 가입한 사용자인지 먼저 확인
if is_already_registered(name, formatted_phone):
raise forms.ValidationError('이미 가입한 유저입니다')
# 허가되지 않은 사용자인지 확인
if not is_allowed_person(name, formatted_phone):
raise forms.ValidationError('초대되지 않은 사용자입니다')
return cleaned_data
class Step2AccountForm(forms.Form):
password1 = forms.CharField(
label='Password',
widget=forms.PasswordInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': 'Password'
})
)
password2 = forms.CharField(
label='Password (again)',
widget=forms.PasswordInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': 'Password (again)'
})
)
privacy_agreement = forms.BooleanField(
required=True,
label='정보공개 및 개인정보처리방침 동의',
error_messages={
'required': '회원가입을 계속하기 위해서 정보공개 등에 동의해주세요'
},
widget=forms.CheckboxInput(attrs={
'class': 'w-4 h-4 text-blue-600 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2'
})
)
def clean(self):
cleaned_data = super().clean()
password1 = cleaned_data.get('password1')
password2 = cleaned_data.get('password2')
privacy_agreement = cleaned_data.get('privacy_agreement')
if password1 and password2 and password1 != password2:
raise forms.ValidationError('비밀번호가 일치하지 않습니다.')
return cleaned_data
def save(self, name, phone, request, commit=True):
# 전화번호 포맷팅 적용
formatted_phone = format_phone_number(phone)
# 기존 사용자가 있는지 확인 (전화번호로)
existing_user = User.objects.filter(username=formatted_phone).first()
if existing_user:
# 해당 User와 연결된 Person이 있는 경우 (이미 회원가입한 상태)
try:
person = Person.objects.get(user=existing_user)
print(f"[DEBUG] 기존 회원가입 사용자 발견: {existing_user.username}")
return existing_user
except Person.DoesNotExist:
pass
try:
# 새 사용자 생성 (전화번호를 username으로 사용)
user = User.objects.create_user(
username=formatted_phone,
email='', # 이메일은 빈 값으로 설정
password=self.cleaned_data['password1'],
first_name=name
)
# 기존 Person 정보가 있는지 확인 (user가 없는 상태)
# 전화번호는 대시 제거하여 비교
existing_person = Person.objects.filter(
이름=name,
user__isnull=True
).first()
# 전화번호 비교 (대시 제거하여)
if existing_person:
person_phone_clean = re.sub(r'[^0-9]', '', existing_person.연락처)
if person_phone_clean != formatted_phone:
existing_person = None
if existing_person:
# 기존 미가입 Person이 있으면 user 연결하고 가입일시 설정
from django.utils import timezone
existing_person.user = user
existing_person.가입일시 = timezone.now()
existing_person.save()
print(f"[DEBUG] 기존 Person 업데이트: {name} (user 연결, 가입일시 기록)")
return user
else:
# 기존 Person이 없으면 새로 생성하고 가입일시 설정
from django.utils import timezone
Person.objects.create(
user=user,
이름=name,
연락처=format_phone_with_dash(formatted_phone), # 대시 있는 전화번호로 저장
소속='',
직책='',
주소='',
사진='profile_photos/default_user.png',
가입일시=timezone.now() # 회원가입 완료 시점 기록
)
print(f"[DEBUG] 새 Person 생성: {name} (가입일시 기록)")
return user
except Exception as e:
print(f"[DEBUG] 사용자 생성 중 오류: {e}")
# 이미 존재하는 사용자인 경우 기존 사용자 반환
existing_user = User.objects.filter(username=formatted_phone).first()
if existing_user:
return existing_user
raise e
class PhoneVerificationForm(forms.Form):
"""전화번호 인증 폼"""
name = forms.ChoiceField(
choices=[('', '이름을 선택하세요')] + [(name, name) for name in get_allowed_names()],
label='이름',
widget=forms.Select(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition'
})
)
phone = forms.CharField(
max_length=11,
label='전화번호',
widget=forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': '01012345678'
})
)
verification_code = forms.CharField(
max_length=6,
label='인증번호',
widget=forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': '6자리 인증번호'
})
)
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')
phone = cleaned_data.get('phone')
if name and phone:
# 전화번호 포맷팅 적용 (대시 제거)
formatted_phone = format_phone_number(phone)
cleaned_data['phone'] = formatted_phone
if not is_allowed_person(name, formatted_phone):
raise forms.ValidationError('이름과 전화번호가 일치하지 않습니다.')
return cleaned_data
class PersonForm(forms.ModelForm):
"""Person 모델 폼"""
class Meta:
model = Person
fields = ['이름', '소속', '직책', '연락처', '주소', '생년월일', '사진', 'keyword1']
widgets = {
'이름': forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-200 bg-opacity-80 text-gray-500 border border-gray-300 focus:outline-none',
'readonly': True,
'tabindex': '-1',
}),
'소속': forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition'
}),
'직책': forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition'
}),
'연락처': forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-200 bg-opacity-80 text-gray-500 border border-gray-300 focus:outline-none',
'readonly': True,
'tabindex': '-1',
}),
'주소': forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition'
}),
'생년월일': forms.DateInput(attrs={
'type': 'date',
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition'
}),
'사진': CustomFileInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition'
}),
'keyword1': forms.TextInput(attrs={
'class': 'w-full px-4 py-3 rounded-xl bg-gray-700 bg-opacity-80 text-white placeholder-gray-400 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 transition',
'placeholder': '검색 키워드 (예: 회계감사)'
}),
}