diff --git a/config/settings.py b/config/settings.py
index f8034db..7a89a6c 100644
--- a/config/settings.py
+++ b/config/settings.py
@@ -176,7 +176,8 @@ REST_FRAMEWORK = {
}
-FRONTEND_URL = 'http://rogainig.intranet.sumasen.net/' # フロントエンドのURLに適宜変更してください
+#FRONTEND_URL = 'https://rogaining.intranet.sumasen.net' # フロントエンドのURLに適宜変更してください
+FRONTEND_URL = 'https://rogaining.sumasen.net' # フロントエンドのURLに適宜変更してください
# この設定により、メールは実際には送信されず、代わりにコンソールに出力されます。
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
@@ -186,10 +187,12 @@ EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'rogaining@gifuai.net'
EMAIL_HOST_PASSWORD = 'ctcpy9823"x~'
-DEFAULT_FROM_EMAIL = 'info@gifuai.net'
+DEFAULT_FROM_EMAIL = 'rogaining@gifuai.net'
-APP_DOWNLOAD_LINK = 'http://your-app-download-link.com'
-SERVICE_NAME = '岐阜ロゲ'
+APP_DOWNLOAD_LINK = 'https://apps.apple.com/jp/app/%E5%B2%90%E9%98%9C%E3%83%8A%E3%83%93/id6444221792'
+ANDROID_DOWNLOAD_LINK = 'https://play.google.com/store/apps/details?id=com.dvox.gifunavi&hl=ja'
+
+SERVICE_NAME = '岐阜ナビ(岐阜ロゲのアプリ)'
# settings.py
DEFAULT_CHARSET = 'utf-8'
diff --git a/rog/migrations/0040_auto_20240801_1310.py b/rog/migrations/0040_auto_20240801_1310.py
new file mode 100644
index 0000000..aaf6414
--- /dev/null
+++ b/rog/migrations/0040_auto_20240801_1310.py
@@ -0,0 +1,33 @@
+# Generated by Django 3.2.9 on 2024-08-01 04:10
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('rog', '0039_auto_20240726_1508'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='member',
+ name='date_of_birth',
+ field=models.DateField(blank=True, null=True),
+ ),
+ migrations.AddField(
+ model_name='member',
+ name='female',
+ field=models.BooleanField(default=False),
+ ),
+ migrations.AddField(
+ model_name='member',
+ name='firstname',
+ field=models.CharField(blank=True, max_length=255, null=True),
+ ),
+ migrations.AddField(
+ model_name='member',
+ name='lastname',
+ field=models.CharField(blank=True, max_length=255, null=True),
+ ),
+ ]
diff --git a/rog/models.py b/rog/models.py
index da4944f..30ba2e3 100644
--- a/rog/models.py
+++ b/rog/models.py
@@ -301,6 +301,11 @@ class Team(models.Model):
class Member(models.Model):
team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='members')
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
+ firstname = models.CharField(max_length=255, blank=True, null=True)
+ lastname = models.CharField(max_length=255, blank=True, null=True)
+ date_of_birth = models.DateField(null=True, blank=True)
+ female = models.BooleanField(default=False)
+
is_temporary = models.BooleanField(default=False) # Akira 2024-7-24
class Meta:
diff --git a/rog/serializers.py b/rog/serializers.py
index 92b3ade..b81bfcf 100644
--- a/rog/serializers.py
+++ b/rog/serializers.py
@@ -481,8 +481,8 @@ class MemberCreationSerializer(serializers.Serializer):
#email = serializers.EmailField()
email = serializers.EmailField(allow_blank=True, required=False)
- firstname = serializers.CharField(required=False)
- lastname = serializers.CharField(required=False)
+ firstname = serializers.CharField(required=False, allow_blank=True)
+ lastname = serializers.CharField(required=False, allow_blank=True)
date_of_birth = serializers.DateField(required=False)
female = serializers.BooleanField(required=False)
@@ -495,7 +495,80 @@ class MemberWithUserSerializer(serializers.ModelSerializer):
fields = ['user', 'team']
class MemberSerializer(serializers.ModelSerializer):
+ email = serializers.EmailField(write_only=True)
+ firstname = serializers.CharField(required=False, allow_blank=True, allow_null=True)
+ lastname = serializers.CharField(required=False, allow_blank=True, allow_null=True)
+ date_of_birth = serializers.DateField(required=False, allow_null=True)
+ female = serializers.BooleanField(required=False)
+
+ class Meta:
+ model = Member
+ fields = ['id', 'email', 'firstname', 'lastname', 'date_of_birth', 'female']
+
+ def validate_firstname(self, value):
+ return value or None
+
+ def validate_lastname(self, value):
+ return value or None
+
+ def create(self, validated_data):
+ email = validated_data.pop('email')
+ team = self.context['team']
+
+ # 既存のユーザーを探すか、新しいユーザーを作成
+ user, created = CustomUser.objects.get_or_create(email=email)
+
+ # ユーザーが新しく作成された場合のみ、追加情報を更新
+ if created:
+ user.firstname = validated_data.get('firstname', '')
+ user.lastname = validated_data.get('lastname', '')
+ user.date_of_birth = validated_data.get('date_of_birth')
+ user.female = validated_data.get('female', False)
+ user.save()
+
+ # メンバーを作成
+ member = Member.objects.create(
+ user=user,
+ team=team,
+ firstname=validated_data.get('firstname'),
+ lastname=validated_data.get('lastname'),
+ date_of_birth=validated_data.get('date_of_birth'),
+ female=validated_data.get('female', False)
+ )
+
+ return member
+ # メンバーを作成して返す
+ #class MemberCreationSerializerreturn Member.objects.create(user=user, team=team)
+
+ def update(self, instance, validated_data):
+ user_data = validated_data.pop('user', {})
+ user = instance.user
+
+ for attr, value in user_data.items():
+ setattr(user, attr, value)
+ user.save()
+
+ return super().update(instance, validated_data)
+
+ def to_representation(self, instance):
+ representation = super().to_representation(instance)
+ representation['email'] = instance.user.email
+ representation['firstname'] = instance.user.firstname
+ representation['lastname'] = instance.user.lastname
+ representation['date_of_birth'] = instance.user.date_of_birth
+ representation['female'] = instance.user.female
+ return representation
+
+
+
+class MemberSerializerOld(serializers.ModelSerializer):
user = CustomUserSerializer(read_only=True)
+ firstname = serializers.CharField(required=False, allow_blank=True, allow_null=True)
+ lastname = serializers.CharField(required=False, allow_blank=True, allow_null=True)
+ date_of_birth = serializers.DateField(required=False, allow_null=True)
+ female = serializers.BooleanField(required=False)
+
+
#team = TeamDetailSerializer(read_only=True)
#email = serializers.EmailField(write_only=True, required=False)
@@ -506,8 +579,8 @@ class MemberSerializer(serializers.ModelSerializer):
class Meta:
model = Member
- fields = ['id','user','team'] # ,'email','firstname','lastname','date_of_birth','female']
- read_only_fields = ['id', 'team']
+ fields = ['id','email','firstname','lastname','date_of_birth','female']
+ #read_only_fields = ['id', 'team']
'''
@@ -530,6 +603,25 @@ class MemberSerializer(serializers.ModelSerializer):
return member
'''
+ def create(self, validated_data):
+ email = validated_data.pop('email')
+ team = self.context['team']
+
+ # 既存のユーザーを探すか、新しいユーザーを作成
+ user, created = CustomUser.objects.get_or_create(email=email)
+
+ # メンバーを作成
+ member = Member.objects.create(
+ user=user,
+ team=team,
+ firstname=validated_data.get('firstname', ''),
+ lastname=validated_data.get('lastname', ''),
+ date_of_birth=validated_data.get('date_of_birth'),
+ female=validated_data.get('female', False)
+ )
+
+ return member
+
def update(self, instance, validated_data):
user_data = validated_data.pop('user', {})
@@ -551,6 +643,12 @@ class MemberSerializer(serializers.ModelSerializer):
#return super().update(instance, validated_data)
+ def to_representation(self, instance):
+ representation = super().to_representation(instance)
+ representation['email'] = instance.user.email
+ return representation
+
+'''
def to_representation(self, instance):
representation = super().to_representation(instance)
user_data = representation['user']
@@ -563,7 +661,7 @@ class MemberSerializer(serializers.ModelSerializer):
'female': user_data['female'],
'team': representation['team']
}
-
+'''
class EntryMemberSerializer(serializers.ModelSerializer):
class Meta:
diff --git a/rog/templates/activation-template.html b/rog/templates/activation-template.html
new file mode 100644
index 0000000..d278c2a
--- /dev/null
+++ b/rog/templates/activation-template.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ アクティベーション成功
+
+
+
+
+
アクティベーション成功
+
{{ message }}
+
+
+
diff --git a/rog/templates/email/verification_email.txt b/rog/templates/email/verification_email.txt
index 3108689..5fb3711 100644
--- a/rog/templates/email/verification_email.txt
+++ b/rog/templates/email/verification_email.txt
@@ -12,6 +12,7 @@
リンクをタップすると、アプリからログインすることができるようになります。
ログインした後は、チーム編成やエントリーまたはチームへの参加を行ってください。
+すでにメンバーとして登録されている場合には、自動的にメンバー登録されます。
なお、リアルロゲイニングは別途申し込みが必要になりますので、ご連絡をお待ちください。
それでは、岐阜ロゲアプリ「岐阜ナビ」をお楽しみください。
diff --git a/rog/templates/verification-template.html b/rog/templates/verification-template.html
new file mode 100644
index 0000000..cb60924
--- /dev/null
+++ b/rog/templates/verification-template.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ メール確認成功
+
+
+
+
+
メール確認成功
+
{{ message }}
+
+
+
diff --git a/rog/urls.py b/rog/urls.py
index 3859398..05cdfc2 100644
--- a/rog/urls.py
+++ b/rog/urls.py
@@ -1,7 +1,7 @@
from sys import prefix
from rest_framework import urlpatterns
from rest_framework.routers import DefaultRouter
-from .views import LocationViewSet, Location_lineViewSet, Location_polygonViewSet, Jpn_Main_PerfViewSet, LocationsInPerf, ExtentForSubPerf, SubPerfInMainPerf, ExtentForMainPerf, LocationsInSubPerf, CatView, RegistrationAPI, LoginAPI, UserAPI, UserActionViewset, UserMakeActionViewset, UserDestinations, UpdateOrder, LocationInBound, DeleteDestination, CustomAreaLocations, GetAllGifuAreas, CustomAreaNames, userDetials, UserTracksViewSet, CatByCity, ChangePasswordView, GoalImageViewSet, CheckinImageViewSet, ExtentForLocations, DeleteAccount, PrivacyView, RegistrationView, TeamViewSet,MemberViewSet,EntryViewSet,RegisterView, VerifyEmailView, NewEventListView,NewEvent2ListView,NewCategoryListView,CategoryListView, MemberUserDetailView, TeamMembersWithUserView,MemberAddView,UserActivationView,RegistrationView,TempUserRegistrationView,ResendInvitationEmailView,update_user_info
+from .views import LocationViewSet, Location_lineViewSet, Location_polygonViewSet, Jpn_Main_PerfViewSet, LocationsInPerf, ExtentForSubPerf, SubPerfInMainPerf, ExtentForMainPerf, LocationsInSubPerf, CatView, RegistrationAPI, LoginAPI, UserAPI, UserActionViewset, UserMakeActionViewset, UserDestinations, UpdateOrder, LocationInBound, DeleteDestination, CustomAreaLocations, GetAllGifuAreas, CustomAreaNames, userDetials, UserTracksViewSet, CatByCity, ChangePasswordView, GoalImageViewSet, CheckinImageViewSet, ExtentForLocations, DeleteAccount, PrivacyView, RegistrationView, TeamViewSet,MemberViewSet,EntryViewSet,RegisterView, VerifyEmailView, NewEventListView,NewEvent2ListView,NewCategoryListView,CategoryListView, MemberUserDetailView, TeamMembersWithUserView,MemberAddView,UserActivationView,RegistrationView,TempUserRegistrationView,ResendInvitationEmailView,update_user_info,update_user_detail,ActivateMemberView, ActivateNewMemberView
from django.urls import path, include
from knox import views as knox_views
@@ -34,6 +34,7 @@ router.register(prefix='checkinimage', viewset=CheckinImageViewSet, basename='ch
router.register(r'entry', EntryViewSet, basename='entry')
router.register(r'teams', TeamViewSet, basename='team')
router.register(r'members', MemberViewSet, basename='member')
+router.register(r'teams/(?P\d+)/members', MemberViewSet, basename='team-members')
# Akira 追加
@@ -86,5 +87,8 @@ urlpatterns += [
#path('register/temp/', RegisterView.as_view(), name='register'), # 古い仮登録
path('reactivate//',ResendInvitationEmailView.as_view(),name='reactivate'),
path('userinfo//', update_user_info, name='update_user_info'),
- path('userdetail//',update_user_info, name='update_user_detail')
+ path('userdetail//',update_user_detail, name='update_user_detail'),
+ path('activate-member///', ActivateMemberView.as_view(), name='activate-member'),
+ path('activate-new-member///', ActivateNewMemberView.as_view(), name='activate-new-member'),
+
]
diff --git a/rog/utils.py b/rog/utils.py
index ef6651c..a6719da 100644
--- a/rog/utils.py
+++ b/rog/utils.py
@@ -3,6 +3,8 @@ from django.template.loader import render_to_string
from django.conf import settings
import logging
from django.core.mail import send_mail
+from django.urls import reverse
+import uuid
logger = logging.getLogger(__name__)
@@ -46,7 +48,12 @@ def send_verification_email(user, activation_link):
# 既にユーザーになっている人にチームへの参加要請メールを出す。
#
-def send_team_join_email(sender,user,team,activation_link):
+def send_team_join_email(sender,user,team):
+ activation_link = request.build_absolute_uri(
+ reverse('activate-member', args=[user.id, team.id])
+ )
+ logger.info(f"request: {request}")
+
context = {
'name': user.lastname or user.email,
'invitor': sender.lastname,
@@ -63,22 +70,31 @@ def send_team_join_email(sender,user,team,activation_link):
# その人がユーザー登録して、ユーザー登録されるとメンバーになる。
# アプリからユーザー登録するため、アプリのダウンロードリンクも送る。
#
-def send_invitation_email(sender,user,team,activation_link):
+def send_invitation_email(sender,request,user_email,team):
+
+ verification_code = uuid.uuid4() # UUIDを生成
+ activation_link = request.build_absolute_uri(
+ reverse('activate-new-member', args=[verification_code, team.id])
+ )
+
+
context = {
- 'name': user.firstname or user.email,
+ 'name': user_email,
'invitor': sender.lastname,
+ 'team_name': team.team_name,
+ 'activation_link': activation_link,
'app_download_link': settings.APP_DOWNLOAD_LINK,
'android_download_link': settings.ANDROID_DOWNLOAD_LINK,
}
subject, body = load_email_template('invitation_new_email.txt', context)
- share_send_email(subject,body,user.email)
+ share_send_email(subject,body,user_email)
# 招待された後にユーザー登録された場合、ヴェリフィケーションでチーム参加登録される。
#
-def send_invitaion_and_verification_email(sender, user, team, activation_link):
+def send_invitaion_and_verification_email(user, team, activation_link):
context = {
'name': user.firstname or user.email,
'activation_link': activation_link,
diff --git a/rog/views.py b/rog/views.py
index e13c217..f6ba03c 100644
--- a/rog/views.py
+++ b/rog/views.py
@@ -1,3 +1,4 @@
+import requests
from rest_framework import serializers
from django.db import IntegrityError
from django.urls import reverse
@@ -158,6 +159,7 @@ def update_user_detail(request, user_id):
setattr(user, field, data[field])
new_value = getattr(user, field)
if old_value != new_value:
+ logger.debug(f"{field}: {old_value} -> {new_value}")
updated_fields.append(f"{field}: {old_value} -> {new_value}")
logger.debug(f"Fields to be updated: {updated_fields}")
@@ -167,6 +169,12 @@ def update_user_detail(request, user_id):
logger.info(f"User {user_id} updated. Changed fields: {', '.join(updated_fields)}")
+ # 更新されたUserデータを使用して関連するMemberのデータを更新
+ members = Member.objects.filter(user=user)
+ for member in members:
+ member.is_temporary = False
+ member.save()
+
serializer = CustomUserSerializer(user)
return Response(serializer.data, status=status.HTTP_200_OK)
@@ -832,20 +840,8 @@ class NewEventListView(generics.ListAPIView):
serializer_class = NewEventSerializer
permission_classes = [IsAuthenticated]
-def update_external_system(zekken_number, event_code, team_name, class_name, password):
- api_url = f"{settings.FRONTEND_URL}/gifuroge/update_team_name"
- data = {
- "zekken_number": zekken_number,
- "new_team_name": team_name,
- "event_code": event_code
- }
- try:
- response = requests.post(api_url, json=data)
- response.raise_for_status()
- return True
- except requests.RequestException as e:
- logger.error(f"Failed to update external system. Error: {str(e)}")
- return False
+
+
class TeamViewSet(viewsets.ModelViewSet):
serializer_class = TeamSerializer
@@ -855,6 +851,8 @@ class TeamViewSet(viewsets.ModelViewSet):
return Team.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
+ logger.info(f"Creating new team for user: {self.request.user.email}")
+
with transaction.atomic():
category = serializer.validated_data['category']
@@ -864,12 +862,12 @@ class TeamViewSet(viewsets.ModelViewSet):
category.save()
category.refresh_from_db() # F() 式の結果を評価
- serializer.save(owner=self.request.user, zekken_number=zekken_number)
-
- team = self.get_object()
+ team = serializer.save(owner=self.request.user, zekken_number=zekken_number)
+ logger.info(f"Team created successfully: {team.id}")
# 外部システムの更新
- success = update_external_system(
+ success = self.register_team(
+ team.owner,
team.zekken_number,
team.owner.event_code,
team.team_name,
@@ -877,21 +875,93 @@ class TeamViewSet(viewsets.ModelViewSet):
team.owner.password
)
if not success:
+ logger.error("Failed to register external system")
raise serializers.ValidationError("外部システムの更新に失敗しました。")
+ logger.info("External system register successfully")
+ def register_team(self, owner,zekken_number,event_code,team_name,category_name,password):
+ logger.info(f"register_team ==> zekken_number={zekken_number},event_code={event_code},team_name={team_name},category_name={category_name},password={password}")
+ api_url = f"{settings.FRONTEND_URL}/gifuroge/register_team"
+ user = owner
+
+ headers = {
+ "Content-Type": "application/x-www-form-urlencoded"
+ }
+ data = {
+ "zekken_number": zekken_number,
+ "event_code": event_code,
+ "team_name": team_name,
+ "class_name": category_name,
+ "password": password # パスワードの扱いに注意が必要です
+ }
+
+ try:
+ response = requests.post(api_url,headers=headers,data=data)
+ response.raise_for_status()
+ logger.info(f"Team registered successfully for team {team_name}")
+ return True
+
+ except requests.RequestException as e:
+ logger.error(f"Failed to register team for entry {entry.id}. Error: {str(e)}")
+ # エラーが発生しても、エントリー自体は作成されています
+ # 必要に応じて、ここでエラーハンドリングを追加できます
+ return False
def destroy(self, request, *args, **kwargs):
team = self.get_object()
if team.members.exists():
- return Response({"error": "チームにメンバーが残っているため削除できません。"}, status=status.HTTP_400_BAD_REQUEST)
+ return Response(
+ {
+ "error": "チームにメンバーが残っているため削除できません。",
+ "error_code": "TEAM_HAS_MEMBERS"
+ },
+ status=status.HTTP_400_BAD_REQUEST
+ )
+
+ #return Response({"error": "チームにメンバーが残っているため削除できません。"}, status=status.HTTP_400_BAD_REQUEST)
return super().destroy(request, *args, **kwargs)
+ def update_external_system(zekken_number, event_code, team_name, class_name, password):
+ api_url = f"{settings.FRONTEND_URL}/gifuroge/update_team_name"
+ headers = {
+ "Content-Type": "application/x-www-form-urlencoded"
+ }
+ data = {
+ "zekken_number": zekken_number,
+ "new_team_name": team_name,
+ "event_code": event_code,
+ }
+ try:
+ response = requests.post(api_url,headers=headers, data=data)
+ response.raise_for_status()
+
+ return True
+ except requests.RequestException as e:
+ logger.error(f"Failed to update external system. Error: {str(e)}")
+ return False
+
def update(self, request, *args, **kwargs):
try:
- return super().update(request, *args, **kwargs)
+ partial = kwargs.pop('partial', False)
+ instance = self.get_object()
+ serializer = self.get_serializer(instance, data=request.data, partial=partial)
+ serializer.is_valid(raise_exception=True)
+ self.perform_update(serializer)
+
+ if getattr(instance, '_prefetched_objects_cache', None):
+ instance._prefetched_objects_cache = {}
+
+ return Response(serializer.data)
except Exception as e:
return Response({"error": "更新に失敗しました。競合が発生した可能性があります。"}, status=status.HTTP_409_CONFLICT)
+
+# def update(self, request, *args, **kwargs):
+# try:
+# return super().update(request, *args, **kwargs)
+# except Exception as e:
+# return Response({"error": "更新に失敗しました。競合が発生した可能性があります。"}, status=status.HTTP_409_CONFLICT)
+
def perform_update(self, serializer):
with transaction.atomic():
team = serializer.save()
@@ -906,7 +976,8 @@ class TeamViewSet(viewsets.ModelViewSet):
)
if not success:
raise serializers.ValidationError("外部システムの更新に失敗しました。")
-
+ else:
+ print("岐阜ロゲシステム更新に成功")
@action(detail=True, methods=['post'])
def copy(self, request, pk=None):
@@ -1004,27 +1075,6 @@ class EntryViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
- def register_team(self, entry):
- api_url = f"{settings.FRONTEND_URL}/gifuroge/register_team"
- user = self.request.user
-
- data = {
- "zekken_number": entry.team.zekken_number,
- "event_code": entry.event.event_code,
- "team_name": entry.team.team_name,
- "class_name": entry.category.category_name,
- "password": user.password # パスワードの扱いに注意が必要です
- }
-
- try:
- response = requests.post(api_url, data=data)
- response.raise_for_status()
- logger.info(f"Team registered successfully for entry {entry.id}")
- except requests.RequestException as e:
- logger.error(f"Failed to register team for entry {entry.id}. Error: {str(e)}")
- # エラーが発生しても、エントリー自体は作成されています
- # 必要に応じて、ここでエラーハンドリングを追加できます
-
def update(self, request, *args, **kwargs):
logger.info(f"Update method called for Entry with ID: {kwargs.get('pk')}")
@@ -1074,7 +1124,7 @@ class EntryViewSet(viewsets.ModelViewSet):
class MemberViewSet(viewsets.ModelViewSet):
- #serializer_class = MemberSerializer
+ serializer_class = MemberSerializer
permission_classes = [permissions.IsAuthenticated,IsTeamOwner]
def get_serializer_class(self):
@@ -1086,12 +1136,64 @@ class MemberViewSet(viewsets.ModelViewSet):
team_id = self.kwargs['team_id']
return Member.objects.filter(team_id=team_id)
+ @action(detail=False, methods=['DELETE'])
+ def destroy_all(self, request, team_id=None):
+ team = Team.objects.get(id=team_id)
+
+ # チームのオーナーかどうかを確認
+ if team.owner != request.user:
+ return Response({"error": "チームのオーナーのみがメンバーを一括削除できます。"}, status=status.HTTP_403_FORBIDDEN)
+
+ # 確認パラメータをチェック
+ confirm = request.query_params.get('confirm', '').lower()
+ if confirm != 'true':
+ return Response({"error": "確認パラメータが必要です。'?confirm=true'を追加してください。"}, status=status.HTTP_400_BAD_REQUEST)
+
+ try:
+ with transaction.atomic():
+ # オーナー以外のすべてのメンバーを削除
+ #deleted_count = Member.objects.filter(team=team).exclude(user=team.owner).delete()[0]
+ deleted_count = Member.objects.filter(team=team).delete()[0]
+
+ return Response({
+ "message": f"{deleted_count}人のメンバーが削除されました。",
+ "deleted_count": deleted_count
+ }, status=status.HTTP_200_OK)
+
+ except Exception as e:
+ return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ def destroy(self, request, *args, **kwargs):
+ instance = self.get_object()
+ team = instance.team
+
+ # チームのオーナーかどうかを確認
+ if team.owner != request.user:
+ return Response({"error": "チームのオーナーのみがメンバーを削除できます。"}, status=status.HTTP_403_FORBIDDEN)
+
+ # オーナー自身は削除できないようにする
+ #if instance.user == team.owner:
+ # return Response({"error": "チームのオーナーは削除できません。"}, status=status.HTTP_400_BAD_REQUEST)
+
+ self.perform_destroy(instance)
+ return Response(status=status.HTTP_204_NO_CONTENT)
+
def create(self, request, *args, **kwargs):
+ logger.info(f"Attempting to create new member for team: {self.kwargs['team_id']}")
+ logger.debug(f"Received data: {request.data}")
+
team = Team.objects.get(id=self.kwargs['team_id'])
- serializer = self.get_serializer(data=request.data)
- serializer.is_valid(raise_exception=True)
+ #serializer = self.get_serializer(data=request.data)
+ serializer = self.get_serializer(data=request.data, context={'team': team})
+
+ try:
+ serializer.is_valid(raise_exception=True)
+ except serializers.ValidationError as e:
+ logger.error(f"Validation error: {e.detail}")
+ return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
email = serializer.validated_data.get('email', '')
+ logger.info(f"Processing member with email: {email}")
user_data = {
'firstname': serializer.validated_data.get('firstname', ''),
@@ -1100,40 +1202,64 @@ class MemberViewSet(viewsets.ModelViewSet):
'female': serializer.validated_data.get('female', False),
}
- if not email or email.startswith('dummy_'):
- # 直接登録
- if email:
- user, created = CustomUser.objects.get_or_create(
- email=email,
- defaults={**user_data, 'is_active':True}
- )
+ # 自分自身を登録する場合
+ if request.user.email == email:
+ member, created = Member.objects.get_or_create(user=request.user, team=team)
+ if created:
+ return Response(MemberSerializer(member).data, status=status.HTTP_201_CREATED)
else:
- # emailが空の場合、一意のダミーメールアドレスを生成
- dummy_email = f"dummy_{uuid.uuid4()}@example.com"
- user = CustomUser.objects.create(email=dummy_email, **user_data)
+ return Response({"message": "You are already a member of this team."}, status=status.HTTP_200_OK)
- member = Member.objects.create(user=user, team=team)
- return Response(MemberSerializer(member).data, status=status.HTTP_201_CREATED)
+ if not email or email.startswith('dummy_'):
+ logger.info("Processing as direct registration")
+ # 直接登録
+ try:
+ if email:
+ user, created = CustomUser.objects.get_or_create(
+ email=email,
+ defaults={**user_data, 'is_active':True}
+ )
+ else:
+ # emailが空の場合、一意のダミーメールアドレスを生成
+ dummy_email = f"dummy_{uuid.uuid4()}@example.com"
+ user = CustomUser.objects.create(email=dummy_email, **user_data)
+
+ member = Member.objects.create(user=user, team=team)
+ logger.info(f"Member created successfully: {member.id}")
+ return Response(MemberSerializer(member).data, status=status.HTTP_201_CREATED)
+ except Exception as e:
+ logger.error(f"Error creating member: {str(e)}")
+ return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
#member = serializer.save(team=team)
#return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
+ logger.info("Processing as temporary registration")
+
# 仮登録
existing_user = CustomUser.objects.filter(email=email).first()
if existing_user:
+ logger.info(f"Existing user found: {existing_user.id}")
+
# 既存ユーザーの場合、チーム招待メールを送信
- send_team_join_email(existing_user, team)
+ send_team_join_email(request.user,existing_user, team)
return Response({"message": "Invitation for your team sent to existing user."}, status=status.HTTP_200_OK)
else:
- print("新規ユーザー")
- temp_user = TempUser.objects.create(
- email=email,
- **user_data,
- verification_code=str(uuid.uuid4())
- )
- send_invitation_email(temp_user, team) #仮登録済みでも確認メールを送る。
+ logger.info("Inviting new temporary user")
- return Response({"message": "Invitation email sent to the user."}, status=status.HTTP_201_CREATED)
+ try:
+ print("新規ユーザー")
+ #temp_user = TempUser.objects.create(
+ # email=email,
+ # **user_data,
+ # verification_code=str(uuid.uuid4())
+ #)
+ send_invitation_email(request.user,request,email, team) #仮登録済みでも確認メールを送る。
+ logger.info(f"Invitation email sent to: {email}")
+ return Response({"message": "Invitation email sent to the user."}, status=status.HTTP_201_CREATED)
+ except Exception as e:
+ logger.info(f"Error on Invitation email sent to: {email} : {e}")
+ return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
'''
@@ -1252,6 +1378,59 @@ class MemberViewSet(viewsets.ModelViewSet):
self.check_object_permissions(self.request, obj)
return obj
+class ActivateMemberView(APIView):
+ def get(self, request, user_id, team_id):
+ user = get_object_or_404(CustomUser, id=user_id)
+ team = get_object_or_404(Team, id=team_id)
+
+ # メンバーオブジェクトを取得または作成
+ member, created = Member.objects.get_or_create(user=user, team=team)
+
+ if member.lastname == "dummy":
+ # userデータでmemberデータを更新
+ member.lastname = user.lastname
+ member.firstname = user.firstname
+ member.date_of_birth = user.date_of_birth
+ member.female = user.female
+ member.save()
+
+ message = f"{team.team_name}に正常に参加し、メンバー情報が更新されました。アプリのチーム管理で確認できます。"
+ else:
+ message = f"{team.team_name}に正常に参加しました。"
+
+ return render(request, 'activation_success.html', {'message': message})
+
+
+class ActivateNewMemberView(APIView):
+ def get(self, request, verification_code, team_id):
+ try:
+ team = Team.objects.get(id=team_id)
+ member, created = Member.objects.get_or_create(team=team, user__email=email)
+ if created:
+ return Response({'message': 'Member activated successfully'}, status=status.HTTP_201_CREATED)
+ else:
+ return Response({'message': 'Member already exists'}, status=status.HTTP_200_OK)
+ except Team.DoesNotExist:
+ return Response({'message': 'Invalid team'}, status=status.HTTP_400_BAD_REQUEST)
+
+'''
+ temp_user = get_object_or_404(TempUser, verification_code=verification_code)
+ team = get_object_or_404(Team, id=team_id)
+
+ user = CustomUser.objects.create_user(
+ email=temp_user.email,
+ password=temp_user.password, # Ensure this is securely handled
+ **{k: v for k, v in temp_user.__dict__.items() if k in ['firstname', 'lastname', 'date_of_birth', 'female']}
+ )
+
+ Member.objects.create(user=user, team=team)
+ temp_user.delete()
+
+ message = f"アカウントが作成され、{team.team_name}に参加しました。アプリのチーム管理で確認できます。"
+ return render(request, 'activation_success.html', {'message': message})
+'''
+
+
class OwnerEntriesView(generics.ListAPIView):
serializer_class = EntrySerializer
permission_classes = [permissions.IsAuthenticated]
@@ -1461,13 +1640,24 @@ class VerifyEmailView(APIView):
password=temp_user.password,
**{k: v for k, v in user_data.items() if k != 'email'}
)
- temp_user.delete()
- return Response({'message': 'Email verified and user created'}, status=status.HTTP_201_CREATED)
+ # チームへの追加処理(もし必要なら)
+ if hasattr(temp_user, 'team_id'):
+ team = Team.objects.get(id=temp_user.team_id)
+ Member.objects.create(user=user, team=team)
+ message = f"メールアドレスが確認され、アカウントが作成されました。{team.team_name}のメンバーとして登録されています。アプリでログインして、必要な情報を入力してください。"
+ else:
+ message = "メールアドレスが確認され、アカウントが作成されました。アプリでログインして、必要な情報を入力してください。"
+
+ temp_user.delete()
+ return render(request, 'verification_success.html', {'message': message})
else:
- return Response({'message': 'Verification link expired'}, status=status.HTTP_400_BAD_REQUEST)
+ message = "確認リンクの有効期限が切れています。アプリから認証コードの再送信をしてください。"
+ return render(request, 'verification_success.html', {'message': message})
+
except TempUser.DoesNotExist:
- return Response({'message': 'Invalid verification code'}, status=status.HTTP_400_BAD_REQUEST)
+ message = "無効な確認コードです。"
+ return render(request, 'verification_success.html', {'message': message})
class MemberUserDetailView(generics.RetrieveAPIView):