From 65d35336be66a351194c291bb08bbfe4dada0f5e Mon Sep 17 00:00:00 2001
From: haeunia <peanutanna@ewhain.net>
Date: Wed, 8 Jan 2025 20:52:38 +0900
Subject: [PATCH 1/2] =?UTF-8?q?=EC=8B=A0=EA=B3=A0=EA=B8=B0=EB=8A=A5=20?=
 =?UTF-8?q?=EC=98=A4=EB=A5=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 market/models.py                              | 14 ++++++
 .../market_serializers/market_serializer.py   |  8 ++++
 .../report_serializer/ReporterSerialzer.py    |  7 +++
 .../serializers/report_serializer/__init__.py |  0
 market/urls.py                                |  5 +-
 market/views/report_views.py                  | 48 +++++++++++++++++++
 6 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 market/serializers/report_serializer/ReporterSerialzer.py
 create mode 100644 market/serializers/report_serializer/__init__.py
 create mode 100644 market/views/report_views.py

diff --git a/market/models.py b/market/models.py
index 5f81b83..a2238db 100644
--- a/market/models.py
+++ b/market/models.py
@@ -6,6 +6,8 @@
 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]
@@ -154,3 +156,15 @@ 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)
+    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}"
+
+
diff --git a/market/serializers/market_serializers/market_serializer.py b/market/serializers/market_serializers/market_serializer.py
index c78c850..fcfd609 100644
--- a/market/serializers/market_serializers/market_serializer.py
+++ b/market/serializers/market_serializers/market_serializer.py
@@ -2,6 +2,14 @@
 
 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/ReporterSerialzer.py
new file mode 100644
index 0000000..19e0e4c
--- /dev/null
+++ b/market/serializers/report_serializer/ReporterSerialzer.py
@@ -0,0 +1,7 @@
+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']
diff --git a/market/serializers/report_serializer/__init__.py b/market/serializers/report_serializer/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/market/urls.py b/market/urls.py
index 5f86e39..178575c 100644
--- a/market/urls.py
+++ b/market/urls.py
@@ -24,7 +24,7 @@
     ServiceStyleCreateListView,
     ServiceStyleView,
 )
-
+from market.views.report_views import ReportUserView
 urlpatterns = [
     path("", MarketCreateListView.as_view(), name="market_create_list"),
     path(
@@ -83,4 +83,7 @@
         ServiceOptionImageUploadView.as_view(),
         name="market_service_option_image_upload",
     ),
+    path('report/', ReportUserView.as_view(), name='report_user'),
+
 ]
+
diff --git a/market/views/report_views.py b/market/views/report_views.py
new file mode 100644
index 0000000..c451d80
--- /dev/null
+++ b/market/views/report_views.py
@@ -0,0 +1,48 @@
+# 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 market.models import Report
+from market.serializers.report_serializer.ReporterSerializer import ReportSerializer
+
+
+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'])
+
+
+            report = Report.objects.create(
+                reported_user=reported_user,
+                reporter_user=reporter_user,
+                reason=data['reason'],
+                details=data.get('details', '')
+            )
+
+
+            report_count = Report.objects.filter(reported_user=reported_user).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({
+                "status": "success",
+                "message": "신고가 접수되었습니다."
+            }, status=status.HTTP_201_CREATED)
+
+        except User.DoesNotExist:
+            return Response({
+                "status": "error",
+                "message": "사용자를 찾을 수 없습니다."
+            }, status=status.HTTP_404_NOT_FOUND)

From 760a609262889bbcd1dd6adcc7edd5e128afeba2 Mon Sep 17 00:00:00 2001
From: haeunia <peanutanna@ewhain.net>
Date: Sat, 11 Jan 2025 16:10:55 +0900
Subject: [PATCH 2/2] =?UTF-8?q?=EC=8B=A0=EA=B3=A0=EA=B8=B0=EB=8A=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 market/migrations/0004_report.py              | 49 +++++++++++++++++++
 market/migrations/0005_alter_report_table.py  | 17 +++++++
 market/models.py                              | 19 ++++---
 .../market_serializers/market_serializer.py   |  8 ---
 ...terSerialzer.py => reporter_serializer.py} |  4 +-
 market/tests.py                               | 15 ++++++
 market/urls.py                                |  7 ++-
 market/views/report_views.py                  | 47 +++++++++---------
 8 files changed, 121 insertions(+), 45 deletions(-)
 create mode 100644 market/migrations/0004_report.py
 create mode 100644 market/migrations/0005_alter_report_table.py
 rename market/serializers/report_serializer/{ReporterSerialzer.py => reporter_serializer.py} (68%)

diff --git a/market/migrations/0004_report.py b/market/migrations/0004_report.py
new file mode 100644
index 0000000..13ef5c9
--- /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 0000000..6351600
--- /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 a2238db..b064a82 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 fcfd609..c78c850 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 19e0e4c..d90625d 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 aef58a3..c76ea99 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 178575c..e4ba15f 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 c451d80..5459f65 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,
+            )