Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions promo_code/business/migrations/0004_promo_comment_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2 on 2025-06-05 11:37

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("business", "0003_promo_like_count"),
]

operations = [
migrations.AddField(
model_name="promo",
name="comment_count",
field=models.PositiveIntegerField(default=0, editable=False),
),
]
8 changes: 8 additions & 0 deletions promo_code/business/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ class Promo(django.db.models.Model):
default=0,
editable=False,
)
comment_count = django.db.models.PositiveIntegerField(
default=0,
editable=False,
)
active_from = django.db.models.DateField(null=True, blank=True)
active_until = django.db.models.DateField(null=True, blank=True)
mode = django.db.models.CharField(
Expand Down Expand Up @@ -107,6 +111,10 @@ def is_active(self) -> bool:
def get_like_count(self) -> int:
return self.like_count

@property
def get_comment_count(self) -> int:
return self.comment_count

@property
def get_used_codes_count(self) -> int:
if self.mode == business.constants.PROMO_MODE_UNIQUE:
Expand Down
10 changes: 10 additions & 0 deletions promo_code/business/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@ class PromoReadOnlySerializer(rest_framework.serializers.ModelSerializer):
source='get_used_codes_count',
read_only=True,
)
comment_count = rest_framework.serializers.IntegerField(
source='get_comment_count',
read_only=True,
)
active = rest_framework.serializers.BooleanField(
source='is_active',
read_only=True,
Expand All @@ -435,6 +439,7 @@ class Meta:
'promo_common',
'promo_unique',
'like_count',
'comment_count',
'used_count',
'active',
)
Expand Down Expand Up @@ -479,6 +484,10 @@ class PromoDetailSerializer(rest_framework.serializers.ModelSerializer):
source='get_like_count',
read_only=True,
)
comment_count = rest_framework.serializers.IntegerField(
source='get_comment_count',
read_only=True,
)
used_count = rest_framework.serializers.IntegerField(
source='get_used_codes_count',
read_only=True,
Expand All @@ -504,6 +513,7 @@ class Meta:
'company_name',
'active',
'like_count',
'comment_count',
'used_count',
)

Expand Down
3 changes: 3 additions & 0 deletions promo_code/user/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@

TARGET_CATEGORY_MIN_LENGTH = 2
TARGET_CATEGORY_MAX_LENGTH = 20

COMMENT_TEXT_MIN_LENGTH = 10
COMMENT_TEXT_MAX_LENGTH = 1000
60 changes: 60 additions & 0 deletions promo_code/user/migrations/0003_promocomment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Generated by Django 5.2 on 2025-06-04 14:26

import django.db.models.deletion
import django.utils.timezone
import uuid
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("business", "0003_promo_like_count"),
("user", "0002_promolike"),
]

operations = [
migrations.CreateModel(
name="PromoComment",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
verbose_name="UUID",
),
),
("text", models.TextField(max_length=1000)),
(
"created_at",
models.DateTimeField(
default=django.utils.timezone.now, editable=False
),
),
("updated_at", models.DateTimeField(auto_now=True)),
(
"author",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comments",
to=settings.AUTH_USER_MODEL,
),
),
(
"promo",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comments",
to="business.promo",
),
),
],
options={
"ordering": ["-created_at"],
},
),
]
34 changes: 34 additions & 0 deletions promo_code/user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,37 @@ class Meta:

def __str__(self):
return f'{self.user} likes {self.promo}'


class PromoComment(django.db.models.Model):
id = django.db.models.UUIDField(
'UUID',
primary_key=True,
default=uuid.uuid4,
editable=False,
)
promo = django.db.models.ForeignKey(
business.models.Promo,
on_delete=django.db.models.CASCADE,
related_name='comments',
)
author = django.db.models.ForeignKey(
User,
on_delete=django.db.models.CASCADE,
related_name='comments',
)
text = django.db.models.TextField(
max_length=user.constants.COMMENT_TEXT_MAX_LENGTH,
)

created_at = django.db.models.DateTimeField(
default=django.utils.timezone.now,
editable=False,
)
updated_at = django.db.models.DateTimeField(auto_now=True)

class Meta:
ordering = ['-created_at']

def __str__(self):
return f'Comment by {self.author.email} on promo {self.promo.id}'
16 changes: 16 additions & 0 deletions promo_code/user/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import rest_framework.permissions


class IsOwnerOrReadOnly(rest_framework.permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit or delete it.
Read-only for others.
"""

def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in rest_framework.permissions.SAFE_METHODS:
return True

return obj.author == request.user
97 changes: 83 additions & 14 deletions promo_code/user/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,12 +341,15 @@ class PromoFeedSerializer(rest_framework.serializers.ModelSerializer):
company_name = rest_framework.serializers.CharField(source='company.name')
active = rest_framework.serializers.BooleanField(source='is_active')
is_activated_by_user = rest_framework.serializers.SerializerMethodField()
is_liked_by_user = rest_framework.serializers.SerializerMethodField()
like_count = rest_framework.serializers.IntegerField(
source='get_like_count',
read_only=True,
)
comment_count = rest_framework.serializers.SerializerMethodField()
comment_count = rest_framework.serializers.IntegerField(
source='get_comment_count',
read_only=True,
)
is_liked_by_user = rest_framework.serializers.SerializerMethodField()

class Meta:
model = business.models.Promo
Expand All @@ -365,18 +368,23 @@ class Meta:

read_only_fields = fields

def get_is_activated_by_user(self, obj) -> bool:
# TODO:
def get_is_liked_by_user(self, obj: business.models.Promo) -> bool:
request = self.context.get('request')
if (
request
and hasattr(request, 'user')
and request.user.is_authenticated
):
return user.models.PromoLike.objects.filter(
promo=obj,
user=request.user,
).exists()
return False

def get_is_liked_by_user(self, obj) -> bool:
def get_is_activated_by_user(self, obj) -> bool:
# TODO:
return False

def get_comment_count(self, obj) -> int:
# TODO:
return 0


class UserPromoDetailSerializer(rest_framework.serializers.ModelSerializer):
"""
Expand Down Expand Up @@ -406,8 +414,11 @@ class UserPromoDetailSerializer(rest_framework.serializers.ModelSerializer):
source='get_like_count',
read_only=True,
)
comment_count = rest_framework.serializers.IntegerField(
source='get_comment_count',
read_only=True,
)
is_liked_by_user = rest_framework.serializers.SerializerMethodField()
comment_count = rest_framework.serializers.SerializerMethodField()

class Meta:
model = business.models.Promo
Expand All @@ -420,8 +431,8 @@ class Meta:
'active',
'is_activated_by_user',
'like_count',
'is_liked_by_user',
'comment_count',
'is_liked_by_user',
)
read_only_fields = fields

Expand All @@ -442,6 +453,64 @@ def get_is_activated_by_user(self, obj) -> bool:
# TODO:
return False

def get_comment_count(self, obj) -> int:
# TODO:
return 0

class UserAuthorSerializer(rest_framework.serializers.ModelSerializer):
name = rest_framework.serializers.CharField(
read_only=True,
min_length=1,
max_length=100,
)
surname = rest_framework.serializers.CharField(
read_only=True,
min_length=1,
max_length=120,
)
avatar_url = rest_framework.serializers.URLField(
read_only=True,
max_length=350,
allow_null=True,
)

class Meta:
model = user.models.User
fields = ('name', 'surname', 'avatar_url')


class CommentSerializer(rest_framework.serializers.ModelSerializer):
id = rest_framework.serializers.UUIDField(read_only=True)
text = rest_framework.serializers.CharField(
min_length=user.constants.COMMENT_TEXT_MIN_LENGTH,
max_length=user.constants.COMMENT_TEXT_MAX_LENGTH,
)
date = rest_framework.serializers.DateTimeField(
source='created_at',
read_only=True,
format='%Y-%m-%dT%H:%M:%S%z',
)
author = UserAuthorSerializer(read_only=True)

class Meta:
model = user.models.PromoComment
fields = ('id', 'text', 'date', 'author')


class CommentCreateSerializer(rest_framework.serializers.ModelSerializer):
text = rest_framework.serializers.CharField(
min_length=user.constants.COMMENT_TEXT_MIN_LENGTH,
max_length=user.constants.COMMENT_TEXT_MAX_LENGTH,
)

class Meta:
model = user.models.PromoComment
fields = ('text',)


class CommentUpdateSerializer(rest_framework.serializers.ModelSerializer):
text = rest_framework.serializers.CharField(
min_length=user.constants.COMMENT_TEXT_MIN_LENGTH,
max_length=user.constants.COMMENT_TEXT_MAX_LENGTH,
)

class Meta:
model = user.models.PromoComment
fields = ('text',)
10 changes: 10 additions & 0 deletions promo_code/user/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,14 @@
user.views.UserPromoLikeView.as_view(),
name='user-promo-like',
),
django.urls.path(
'promo/<uuid:promo_id>/comments',
user.views.PromoCommentListCreateView.as_view(),
name='user-promo-comment-list-create',
),
django.urls.path(
'promo/<uuid:promo_id>/comments/<uuid:comment_id>',
user.views.PromoCommentDetailView.as_view(),
name='user-promo-comment-detail',
),
]
Loading