diff --git a/market/migrations/0004_report.py b/market/migrations/0004_report.py new file mode 100644 index 00000000..13ef5c94 --- /dev/null +++ b/market/migrations/0004_report.py @@ -0,0 +1,49 @@ +# Generated by Django 5.1.1 on 2025-01-11 07:01 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("market", "0003_service_suspended"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="Report", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("reason", models.CharField(max_length=255)), + ("details", models.TextField(blank=True, null=True)), + ("created_at", models.DateTimeField(auto_now_add=True)), + ( + "reported_user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="reports_received", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "reporter_user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="reports_made", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/market/migrations/0005_alter_report_table.py b/market/migrations/0005_alter_report_table.py new file mode 100644 index 00000000..6351600d --- /dev/null +++ b/market/migrations/0005_alter_report_table.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.1 on 2025-01-11 07:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("market", "0004_report"), + ] + + operations = [ + migrations.AlterModelTable( + name="report", + table="report", + ), + ] diff --git a/market/models.py b/market/models.py index a2238db3..b064a821 100644 --- a/market/models.py +++ b/market/models.py @@ -1,13 +1,13 @@ import uuid +from django.conf import settings +from django.contrib.auth.models import User from django.db import models from core.models import TimeStampedModel from market.managers import MarketManager, ServiceManager, ServiceMaterialManager from users.models.reformer import Reformer -from django.db import models -from django.contrib.auth.models import User def get_market_thumbnail_upload_path(instance, filename): email_name = instance.reformer.user.email.split("@")[0] @@ -157,14 +157,17 @@ class ServiceOptionImage(TimeStampedModel): class Meta: db_table = "market_service_option_image" + class Report(models.Model): - reported_user = models.ForeignKey(User, related_name="reports_received", on_delete=models.CASCADE) - reporter_user = models.ForeignKey(User, related_name="reports_made", on_delete=models.CASCADE) + reported_user = models.ForeignKey( + "users.User", related_name="reports_received", on_delete=models.CASCADE + ) + reporter_user = models.ForeignKey( + "users.User", related_name="reports_made", on_delete=models.CASCADE + ) reason = models.CharField(max_length=255) details = models.TextField(blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) - def __str__(self): - return f"Report against {self.reported_user.username} by {self.reporter_user.username}" - - + class Meta: + db_table = "report" diff --git a/market/serializers/market_serializers/market_serializer.py b/market/serializers/market_serializers/market_serializer.py index fcfd609b..c78c850b 100644 --- a/market/serializers/market_serializers/market_serializer.py +++ b/market/serializers/market_serializers/market_serializer.py @@ -2,14 +2,6 @@ from market.models import Market -from rest_framework import serializers -from market.models import Report - -class ReportSerializer(serializers.ModelSerializer): - class Meta: - model = Report - fields = ['reported_user', 'reporter_user', 'reason', 'details'] - class MarketSerializer(serializers.ModelSerializer): market_uuid = serializers.UUIDField(read_only=True) diff --git a/market/serializers/report_serializer/ReporterSerialzer.py b/market/serializers/report_serializer/reporter_serializer.py similarity index 68% rename from market/serializers/report_serializer/ReporterSerialzer.py rename to market/serializers/report_serializer/reporter_serializer.py index 19e0e4c4..d90625d3 100644 --- a/market/serializers/report_serializer/ReporterSerialzer.py +++ b/market/serializers/report_serializer/reporter_serializer.py @@ -1,7 +1,9 @@ from rest_framework import serializers + from market.models import Report + class ReportSerializer(serializers.ModelSerializer): class Meta: model = Report - fields = ['reported_user', 'reporter_user', 'reason', 'details'] + fields = ["reported_user", "reporter_user", "reason", "details"] diff --git a/market/tests.py b/market/tests.py index aef58a33..c76ea99c 100644 --- a/market/tests.py +++ b/market/tests.py @@ -253,6 +253,21 @@ def test_delete_market_info(self, mock_boto3_client: MagicMock): # 마켓 정보가 삭제 되었는지 확인 self.assertEqual(Market.objects.filter(market_uuid=market_uuid).count(), 0) + def test_report_market(self): + # 마켓 신고가 정상적으로 작동하는 것 + response = self.client.post( + path="/api/market/report", + data={ + "reported_user_id": self.test_user.id, + "reason": "허위 정보 게시", + "details": "잘못된 정보를 포함한 마켓 설명", + }, + format="json", + ) + self.assertEqual(response.status_code, 201) + self.assertEqual(response.data["reported_user"], self.test_user.id) + self.assertEqual(response.data["reason"], "허위 정보 게시") + def tearDown(self): Market.objects.all().delete() Reformer.objects.all().delete() diff --git a/market/urls.py b/market/urls.py index 178575c2..e4ba15fb 100644 --- a/market/urls.py +++ b/market/urls.py @@ -7,6 +7,7 @@ ) from market.views.market_view.market_create_list_view import MarketCreateListView from market.views.market_view.market_crud_view import MarketCrudView +from market.views.report_views import ReportUserView from market.views.service_view.service_create_list_view import ( GetAllServiceView, MarketServiceCreateListView, @@ -24,7 +25,7 @@ ServiceStyleCreateListView, ServiceStyleView, ) -from market.views.report_views import ReportUserView + urlpatterns = [ path("", MarketCreateListView.as_view(), name="market_create_list"), path( @@ -83,7 +84,5 @@ ServiceOptionImageUploadView.as_view(), name="market_service_option_image_upload", ), - path('report/', ReportUserView.as_view(), name='report_user'), - + path("/report", ReportUserView.as_view(), name="report_user"), ] - diff --git a/market/views/report_views.py b/market/views/report_views.py index c451d801..5459f65d 100644 --- a/market/views/report_views.py +++ b/market/views/report_views.py @@ -1,48 +1,47 @@ # market/views/report_views.py -from rest_framework.views import APIView -from rest_framework.response import Response from rest_framework import status -from django.contrib.auth.models import User +from rest_framework.response import Response +from rest_framework.views import APIView + from market.models import Report -from market.serializers.report_serializer.ReporterSerializer import ReportSerializer +from market.serializers.report_serializer.reporter_serializer import ReportSerializer +from users.models.user import User class ReportUserView(APIView): def post(self, request): data = request.data try: - reported_user = User.objects.get(id=data['reported_user_id']) - reporter_user = User.objects.get(id=data['reporter_user_id']) + reported_user = User.objects.get(id=data["reported_user_id"]) + reporter_user = User.objects.get(id=request.user.id) - - report = Report.objects.create( + report: Report = Report.objects.create( reported_user=reported_user, reporter_user=reporter_user, - reason=data['reason'], - details=data.get('details', '') + reason=data["reason"], + details=data.get("details", ""), ) - + serializer = ReportSerializer(instance=report) report_count = Report.objects.filter(reported_user=reported_user).count() + serializer.data["report_count"] = report_count - if report_count >= 5: reported_user.is_active = False reported_user.save() - return Response({ - "status": "success", - "message": "신고가 접수되었으며, 해당 사용자의 서비스가 중단됩니다." - }, status=status.HTTP_200_OK) + return Response(data=serializer.data, status=status.HTTP_200_OK) - return Response({ - "status": "success", - "message": "신고가 접수되었습니다." - }, status=status.HTTP_201_CREATED) + return Response(data=serializer.data, status=status.HTTP_201_CREATED) except User.DoesNotExist: - return Response({ - "status": "error", - "message": "사용자를 찾을 수 없습니다." - }, status=status.HTTP_404_NOT_FOUND) + return Response( + {"status": "error", "message": "사용자를 찾을 수 없습니다."}, + status=status.HTTP_404_NOT_FOUND, + ) + except Exception as e: + return Response( + data={"status": "error", "details": str(e)}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR, + )