Merge pull request #70 from plers-org/sm/#69

Sm/#69
This commit is contained in:
NKEY
2025-06-25 23:36:02 +09:00
committed by GitHub
8 changed files with 45 additions and 31 deletions

View File

@@ -13,7 +13,7 @@ class InviteCodeUseType(models.TextChoices):
HACKATHON = 'h', 'h' HACKATHON = 'h', 'h'
class NotificationType(models.TextChoices): class NotificationType(models.TextChoices):
INVITE = '초대', '초대' PROJECT_INVITE = '프로젝트 초대', '프로젝트 초대'
class InvitationStatus(models.TextChoices): class InvitationStatus(models.TextChoices):
PENDING = '대기', '대기' PENDING = '대기', '대기'

View File

@@ -2,6 +2,30 @@ from .models import *
from projects.models import * from projects.models import *
from rest_framework import serializers from rest_framework import serializers
from common.models.choiceModels import NotificationType
NOTIFICATION_REL_MAP_REGISTRY = {
# "model" : "model_cls",
# "serializer" : "serializer_cls"
}
def register_notification_serializer(note_type:NotificationType, model_cls):
def wrapper(serializer_cls):
NOTIFICATION_REL_MAP_REGISTRY[note_type] = {'model' : model_cls, 'serializer' : serializer_cls}
return serializer_cls
return wrapper
@register_notification_serializer(NotificationType.PROJECT_INVITE, ProjectInvitation)
class ProjectInvitationMetaSerializer(serializers.ModelSerializer):
project_invitation_id = serializers.CharField(source='id')
project_title = serializers.CharField(source='project.title')
from_user_nickname = serializers.CharField(source='from_user.nickname')
class Meta:
model = ProjectInvitation
fields = ['project_invitation_id', 'project_title', 'from_user_nickname', 'status']
class NotificationSerializer(serializers.ModelSerializer): class NotificationSerializer(serializers.ModelSerializer):
meta = serializers.SerializerMethodField() meta = serializers.SerializerMethodField()
@@ -10,23 +34,10 @@ class NotificationSerializer(serializers.ModelSerializer):
fields = ['id', 'content', 'note_type', 'is_read', 'created_at', 'meta'] fields = ['id', 'content', 'note_type', 'is_read', 'created_at', 'meta']
def get_meta(self, obj): def get_meta(self, obj):
note_type = obj.note_type
REL_SERIALIZER_MAP = { rel_name = NOTIFICATION_REL_MAP_REGISTRY[note_type]['model']._meta.get_field('notification').remote_field.related_name
'project_invitation' : ProjectInvitationMetaSerializer, rel_obj = getattr(obj, rel_name, None)
} if rel_obj is not None:
return NOTIFICATION_REL_MAP_REGISTRY[note_type]['serializer'](rel_obj).data
for rel_name, serializer_cls in REL_SERIALIZER_MAP.items():
rel_obj = getattr(obj, rel_name, None)
if rel_obj is not None:
return serializer_cls(rel_obj).data
return None return None
class ProjectInvitationMetaSerializer(serializers.ModelSerializer):
project_invitation_id = serializers.CharField(source='id')
project_title = serializers.CharField(source='project.title')
from_user_nickname = serializers.CharField(source='from_user.nickname')
class Meta:
model = ProjectInvitation
fields = ['project_invitation_id', 'project_title', 'from_user_nickname', 'status']

View File

@@ -7,8 +7,9 @@ from rest_framework.routers import DefaultRouter
app_name = 'notifications' app_name = 'notifications'
router = DefaultRouter() router = DefaultRouter()
router.register(r'', NotificationReadViewSet, basename='notification') router.register(r'read', NotificationReadViewSet, basename='notification')
urlpatterns = [ urlpatterns = [
path('', include(router.urls)), path('', include(router.urls)),
path('count/', NewNotificationCountAPIView().as_view()),
] ]

View File

@@ -31,3 +31,10 @@ class NotificationReadViewSet(ReadOnlyModelViewSet):
instance.save() instance.save()
serializer = self.get_serializer(instance) serializer = self.get_serializer(instance)
return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.data, status=status.HTTP_200_OK)
class NewNotificationCountAPIView(APIView):
def get(self, request):
user = request.user
count = UserToNotificationService.get_new_notification_count(user)
return Response({"new_notification_count" : count})

View File

@@ -38,10 +38,10 @@ class ProjectCreateSerializer(serializers.ModelSerializer):
return project return project
users = User.objects.filter(nickname__in=nicknames) users = User.objects.filter(nickname__in=nicknames)
users = list(users) + [validated_data["owner"]] ProjectTeamList.objects.create(project=project, user=validated_data['owner'])
for user in users: for user in users:
new_notification = NotifiationService.create_notification(user=user, note_type=NotificationType.INVITE) new_notification = NotifiationService.create_notification(user=user, note_type=NotificationType.PROJECT_INVITE)
ProjectInvitationService.create_project_invitation( ProjectInvitationService.create_project_invitation(
project=project, project=project,
from_user=validated_data['owner'], from_user=validated_data['owner'],

View File

@@ -50,7 +50,7 @@ class ProjectTeamManageAPIView(APIView):
new_member = get_object_or_404(User, nickname=nickname) new_member = get_object_or_404(User, nickname=nickname)
if ProjectTeamList.objects.filter(project=project, user=new_member).exists(): if ProjectTeamList.objects.filter(project=project, user=new_member).exists():
return Response({"message": "already team member"}, status=status.HTTP_400_BAD_REQUEST) return Response({"message": "already team member"}, status=status.HTTP_400_BAD_REQUEST)
new_notification = NotifiationService.create_notification(user=new_member, note_type=NotificationType.INVITE) new_notification = NotifiationService.create_notification(user=new_member, note_type=NotificationType.PROJECT_INVITE)
ProjectInvitationService.create_project_invitation( ProjectInvitationService.create_project_invitation(
project=project, project=project,
from_user=user, from_user=user,

View File

@@ -5,8 +5,6 @@ from portfolios.models import *
from django.utils import timezone from django.utils import timezone
from datetime import timedelta from datetime import timedelta
# 30일 이전 일수 계산
thirty_days_ago = timezone.now() - timedelta(days=30)
DUPLICATE_CHECK = { DUPLICATE_CHECK = {
'email': 'email', 'email': 'email',
@@ -37,10 +35,12 @@ class CheckUserFieldValueExistService:
class UserToNotificationService: class UserToNotificationService:
@staticmethod @staticmethod
def get_new_notification_count(user: User): def get_new_notification_count(user: User):
thirty_days_ago = timezone.now() - timedelta(days=30)
return user.notifications.filter(created_at__gt=thirty_days_ago, is_read=False).count() return user.notifications.filter(created_at__gt=thirty_days_ago, is_read=False).count()
@staticmethod @staticmethod
def get_all_notification(user: User): def get_all_notification(user: User):
thirty_days_ago = timezone.now() - timedelta(days=30)
return user.notifications.filter(created_at__gt=thirty_days_ago) return user.notifications.filter(created_at__gt=thirty_days_ago)

View File

@@ -227,7 +227,6 @@ class MyPageProfileAPIView(APIView):
serializer = UserProfileSerializer(target_user) serializer = UserProfileSerializer(target_user)
data = serializer.data data = serializer.data
data['represent_portfolio_id'] = UserToPortfolioService.get_represent_portfolio(target_user) data['represent_portfolio_id'] = UserToPortfolioService.get_represent_portfolio(target_user)
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
# 프로필 수정 # 프로필 수정
@@ -245,7 +244,6 @@ class MyPageProfileAPIView(APIView):
serializer.save() serializer.save()
data = serializer.data data = serializer.data
data['represent_portfolio_id'] = UserToPortfolioService.get_represent_portfolio(target_user) data['represent_portfolio_id'] = UserToPortfolioService.get_represent_portfolio(target_user)
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else: else:
@@ -301,8 +299,6 @@ class MyPageWorkListAPIView(APIView):
} }
else: else:
return Response({"message": "not allowed retreive_type"}, status=status.HTTP_400_BAD_REQUEST) return Response({"message": "not allowed retreive_type"}, status=status.HTTP_400_BAD_REQUEST)
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
class MyPageMemberInfoAPIView(APIView): class MyPageMemberInfoAPIView(APIView):
@@ -312,7 +308,6 @@ class MyPageMemberInfoAPIView(APIView):
user = request.user user = request.user
serializer = UserMemberInfoSerializer(user) serializer = UserMemberInfoSerializer(user)
data = serializer.data data = serializer.data
data['new_notification_count'] = UserToNotificationService.get_new_notification_count(user)
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
# 내 정보 수정 # 내 정보 수정