@@ -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 = '대기', '대기'
|
||||||
|
|||||||
@@ -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']
|
|
||||||
|
|
||||||
@@ -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()),
|
||||||
]
|
]
|
||||||
@@ -30,4 +30,11 @@ class NotificationReadViewSet(ReadOnlyModelViewSet):
|
|||||||
instance.is_read = True
|
instance.is_read = True
|
||||||
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})
|
||||||
@@ -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'],
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
# 내 정보 수정
|
# 내 정보 수정
|
||||||
|
|||||||
Reference in New Issue
Block a user