1+ import typing
2+ import uuid
3+
14from core .util .thread_local import get_current_user
5+ from django .db import transaction
26from event .presentation .models import Presentation , PresentationSpeaker
37from file .models import PublicFile
48from participant_portal_api .serializers .modification_audit import ModificationAuditCreationPortalSerializer
711
812class PresentationSpeakerPortalSerializer (serializers .ModelSerializer ):
913 image = serializers .PrimaryKeyRelatedField (queryset = PublicFile .objects .filter_active (), allow_null = True )
14+ user = serializers .PrimaryKeyRelatedField (read_only = True )
1015
1116 class Meta :
1217 model = PresentationSpeaker
1318 fields = ("id" , "biography_ko" , "biography_en" , "image" , "user" )
1419
1520
21+ class PresentationSpeakerPortalData (typing .TypedDict ):
22+ id : str | uuid .UUID
23+ biography_ko : str | None
24+ biography_en : str | None
25+ image : str | uuid .UUID | None
26+
27+
1628class PresentationPortalSerializer (ModificationAuditCreationPortalSerializer , serializers .ModelSerializer ):
1729 title = serializers .CharField (read_only = True )
1830 summary = serializers .CharField (read_only = True )
1931 description = serializers .CharField (read_only = True )
2032
2133 image = serializers .PrimaryKeyRelatedField (queryset = PublicFile .objects .filter_active (), allow_null = True )
22- speakers = PresentationSpeakerPortalSerializer (many = True , read_only = True )
34+ speakers = PresentationSpeakerPortalSerializer (many = True , required = True )
2335
2436 class Meta :
2537 model = Presentation
@@ -40,10 +52,46 @@ class Meta:
4052 "requested_modification_audit_id" ,
4153 )
4254
55+ def get_speaker_instance (self , speaker_id : str | uuid .UUID ) -> PresentationSpeaker | None :
56+ return (
57+ PresentationSpeaker .objects .filter_active ()
58+ .filter (
59+ presentation = self .instance ,
60+ id = speaker_id ,
61+ user = get_current_user (),
62+ )
63+ .first ()
64+ )
65+
4366 def to_representation (self , instance ):
4467 result = super ().to_representation (instance )
4568
4669 if (current_user := get_current_user ()) and (speakers := result .get ("speakers" )):
4770 result ["speakers" ] = [s for s in speakers if s ["user" ] == current_user .pk ]
4871
4972 return result
73+
74+ def create (self , validated_data ):
75+ raise NotImplementedError ("Creation of presentations is not allowed in the participant portal." )
76+
77+ @transaction .atomic
78+ def update (self , presentation , validated_data ):
79+ speakers = typing .cast (list [PresentationSpeakerPortalData ], validated_data ["speakers" ])
80+ if not isinstance (speakers , list ):
81+ raise serializers .ValidationError ("Speakers must be a list." )
82+
83+ for speaker_data in speakers :
84+ if not (speaker_instance := self .get_speaker_instance (speaker_data ["id" ])):
85+ raise serializers .ValidationError (
86+ f"Speaker with ID { speaker_data ['id' ]} not found or does not belong to this presentation."
87+ )
88+
89+ speaker_serializer = PresentationSpeakerPortalSerializer (
90+ instance = speaker_instance ,
91+ data = speaker_data ,
92+ partial = True ,
93+ )
94+ speaker_serializer .is_valid (raise_exception = True )
95+ speaker_serializer .save ()
96+
97+ return super ().update (presentation , validated_data )
0 commit comments