Skip to content

Commit c9d93ae

Browse files
committed
chore: 수정 심사 반영 데이터를 계산하는 방식 변경
1 parent 27657cd commit c9d93ae

File tree

7 files changed

+53
-54
lines changed

7 files changed

+53
-54
lines changed

app/admin_api/serializers/modification_audit.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def validate(self, attrs: dict) -> dict:
4949
def save(self, **kwargs: dict) -> ModificationAudit:
5050
instance: ModificationAudit = self.instance
5151
instance.status = ModificationAudit.Status.APPROVED
52-
instance.apply_modification(save=True)
52+
instance.apply_modification()
53+
instance.save()
5354

5455
return instance
5556

app/admin_api/views/event/presentation.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import annotations
22

3-
import typing
4-
53
from admin_api.filtersets.event.presentation import (
64
PresentationAdminFilterSet,
75
PresentationCategoryAdminFilterSet,
@@ -65,7 +63,7 @@ def preview_modification_audit(self, audit_id: str, *args: tuple, **kwargs: dict
6563
if not (mod_audit := ModificationAudit.objects.filter_requested(presentation).filter(id=audit_id).first()):
6664
return response.Response(status=status.HTTP_404_NOT_FOUND)
6765

68-
return response.Response(data=self.get_serializer(mod_audit.apply_modification(save=False)).data)
66+
return response.Response(mod_audit.join_modification_data(data=self.get_serializer(presentation).data))
6967

7068

7169
@extend_schema_view(**{m: extend_schema(tags=[OpenAPITag.ADMIN_EVENT_PRESENTATION]) for m in ADMIN_METHODS})
@@ -79,11 +77,8 @@ class PresentationSpeakerAdminViewSet(JsonSchemaViewSet, viewsets.ModelViewSet):
7977
@extend_schema(tags=[OpenAPITag.ADMIN_EVENT_PRESENTATION])
8078
@decorators.action(detail=True, methods=["get"], url_path="preview")
8179
def preview_modification_audit(self, request: request.Request, *args: tuple, **kwargs: dict) -> response.Response:
82-
if not (
83-
mod_audit := typing.cast(
84-
ModificationAudit | None, ModificationAudit.objects.filter_requested(self.get_object()).first()
85-
)
86-
):
80+
speaker = self.get_object()
81+
if not (mod_audit := ModificationAudit.objects.filter_requested(self.get_object()).first()):
8782
return response.Response(status=status.HTTP_404_NOT_FOUND)
8883

89-
return response.Response(data=self.get_serializer(mod_audit.apply_modification(save=False)).data)
84+
return response.Response(data=mod_audit.join_modification_data(data=self.get_serializer(speaker).data))

app/admin_api/views/user.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@ def preview_modification_audit(self, audit_id: str, *args: tuple, **kwargs: dict
8686
if not UUID_V4_REGEX.match(audit_id):
8787
return response.Response(status=status.HTTP_404_NOT_FOUND)
8888

89-
user: UserExt = self.get_object()
89+
user = self.get_object()
9090
if not (mod_audit := ModificationAudit.objects.filter_requested(user).filter(id=audit_id).first()):
9191
return response.Response(status=status.HTTP_404_NOT_FOUND)
9292

93-
return response.Response(data=self.get_serializer(mod_audit.apply_modification(save=False)).data)
93+
return response.Response(data=mod_audit.join_modification_data(self.get_serializer(user).data))
9494

9595

9696
@extend_schema_view(**{m: extend_schema(tags=[OpenAPITag.ADMIN_USER]) for m in ADMIN_METHODS})

app/participant_portal_api/models.py

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import copy
12
import typing
23

34
from core.models import BaseAbstractModel, BaseAbstractModelQuerySet
@@ -58,21 +59,38 @@ class Meta:
5859
def __str__(self) -> str:
5960
return str(self.instance)
6061

61-
def apply_modification(self, save: bool = False) -> models.Model:
62+
def join_modification_data(self, data: dict) -> dict:
63+
new_data: dict[str, typing.Any] = copy.deepcopy(self.modification_data)
64+
for field, orig_value in data.items():
65+
if not (mod_data := self.modification_data.get(field)):
66+
continue
67+
68+
if isinstance(orig_value, list):
69+
sub_mod_value_map: dict[str, typing.Any] = {v["id"]: v for v in mod_data}
70+
new_value = []
71+
for orig_sub_value in orig_value[field]:
72+
if not isinstance(orig_sub_value, dict) or not (sub_value_id := orig_sub_value.get("id")):
73+
continue
74+
75+
new_value.append(orig_sub_value | sub_mod_value_map.get(sub_value_id, {}))
76+
77+
new_data[field] = new_value
78+
elif isinstance(orig_value, dict):
79+
# One to One case
80+
new_data[field] = orig_value | mod_data
81+
else:
82+
# 일반 필드 업데이트
83+
new_data[field] = mod_data
84+
85+
return new_data
86+
87+
def apply_modification(self) -> models.Model:
6288
for field, value in self.modification_data.items():
6389
if isinstance(value, list):
6490
# One to Many case
65-
sub_value_map = {sub_value["id"]: sub_value for sub_value in value}
66-
if not (sub_instances := list(getattr(self.instance, field).filter(pk__in=sub_value_map))):
67-
continue
68-
69-
for sub_instance in sub_instances:
70-
sub_data = sub_value_map[str(sub_instance.pk)]
71-
for sub_field, sub_value in sub_data.items():
72-
setattr(sub_instance, sub_field, sub_value)
91+
for sub_value in value:
92+
getattr(self.instance, field).filter(pk=sub_value.pop("id")).update(**sub_value)
7393

74-
if save:
75-
sub_instance.save()
7694
elif isinstance(value, dict):
7795
# One to One case
7896
if not (sub_instance := getattr(self.instance, field, None)):
@@ -81,16 +99,12 @@ def apply_modification(self, save: bool = False) -> models.Model:
8199
for sub_field, sub_value in value.items():
82100
setattr(sub_instance, sub_field, sub_value)
83101

84-
if save:
85-
sub_instance.save()
86-
else:
87-
setattr(self.instance, field, sub_instance)
102+
sub_instance.save()
88103
else:
89104
# 일반 필드 업데이트
90105
setattr(self.instance, field, value)
91106

92-
if save:
93-
self.instance.save()
107+
self.instance.save()
94108

95109
return self.instance
96110

app/participant_portal_api/serializers/modification_audit.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,8 @@ def validate(self, attrs: dict) -> dict:
128128

129129
def save(self, **kwargs: dict) -> models.Model:
130130
"""instance.save()를 호출하는 대신, 변경된 데이터를 추출하여 ModificationAudit 인스턴스를 생성합니다."""
131-
return ModificationAudit.objects.create(
132-
instance=self.instance, modification_data=self.validated_data
133-
).apply_modification(save=False)
131+
ModificationAudit.objects.create(instance=self.instance, modification_data=self.validated_data)
132+
return self.instance
134133

135134

136135
class ModificationAuditCancelPortalSerializer(serializers.ModelSerializer):

app/participant_portal_api/views/presentation.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from participant_portal_api.models import ModificationAudit
55
from participant_portal_api.permissions import IsSessionSpeaker
66
from participant_portal_api.serializers.presentation import PresentationPortalSerializer
7-
from rest_framework import mixins, viewsets
7+
from rest_framework import mixins, response, viewsets
88

99

1010
@utils.extend_schema_view(
@@ -39,9 +39,12 @@ def get_queryset(self):
3939
)
4040
)
4141

42-
def get_object(self):
43-
presentation = super().get_object()
44-
if mod_audit := ModificationAudit.objects.filter_requested(presentation).first():
45-
presentation = mod_audit.apply_modification(save=False)
42+
def retrieve(self, request, *args, **kwargs):
43+
"""발표 조회 시, 수정 요청이 있는 경우 해당 요청의 ID를 포함하여 응답"""
4644

47-
return presentation
45+
instance = self.get_object()
46+
data = self.get_serializer(instance).data
47+
if mod_audit := ModificationAudit.objects.filter_requested(instance).first():
48+
data = mod_audit.join_modification_data(data)
49+
50+
return response.Response(data)

app/participant_portal_api/views/user.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import typing
2-
31
from core.const.tag import OpenAPITag
42
from django.contrib.auth import login, logout
53
from drf_spectacular.utils import extend_schema
@@ -29,10 +27,11 @@ def retrieve_profile(self, request: request.Request, *args: tuple, **kwargs: dic
2927
return response.Response(status=status.HTTP_401_UNAUTHORIZED)
3028

3129
user = request.user
30+
data = self.get_serializer(user).data
3231
if mod_audit := ModificationAudit.objects.filter_requested(user).first():
33-
user = mod_audit.apply_modification(save=False)
32+
data = mod_audit.join_modification_data(data)
3433

35-
return response.Response(data=self.get_serializer(user).data)
34+
return response.Response(data)
3635

3736
@extend_schema(
3837
tags=[OpenAPITag.PARTICIPANT_PORTAL_USER],
@@ -49,18 +48,6 @@ def patch_profile(self, request: request.Request, *args: tuple, **kwargs: dict)
4948

5049
return response.Response(data=UserPortalSerializer(instance).data)
5150

52-
@extend_schema(tags=[OpenAPITag.PARTICIPANT_PORTAL_PRESENTATION])
53-
@decorators.action(detail=False, methods=["get"], url_path="me/preview")
54-
def preview_modification_audit(self, request: request.Request, *args: tuple, **kwargs: dict) -> response.Response:
55-
if not (
56-
mod_audit := typing.cast(
57-
ModificationAudit | None, ModificationAudit.objects.filter_requested(request.user).first()
58-
)
59-
):
60-
return response.Response(status=status.HTTP_404_NOT_FOUND)
61-
62-
return response.Response(data=self.get_serializer(mod_audit.apply_modification(save=False)).data)
63-
6451
@extend_schema(
6552
tags=[OpenAPITag.PARTICIPANT_PORTAL_USER],
6653
request=UserPortalSignInSerializer,

0 commit comments

Comments
 (0)