class CommunicationMessageObjectSerializer(ReprSerializerMixin, ContentTypeSerializerMixin, serializers.Serializer): id = serializers.IntegerField() class CommunicationMessageRecipientSerializer(serializers.Serializer): recipient_type = ContentTypeField() recipient_id = serializers.IntegerField() class MultipleCommunicationMessageRecipientSerializer(serializers.ListSerializer): child = CommunicationMessageRecipientSerializer() class CommunicationMessageEmailRecipientSerializer(serializers.Serializer): email = serializers.EmailField() class MultipleCommunicationMessageEmailRecipientSerializer(serializers.ListSerializer): child = CommunicationMessageEmailRecipientSerializer() def _validate_recipients(attrs, sub_matter): if not attrs.get('recipients') and len(attrs.get('email_recipients', [])) == 0: raise serializers.ValidationError({'recipients': 'This field is required.'}) for recipient_obj in attrs.get('recipients', []): ct = recipient_obj['recipient_type'] if ".".join(ct.natural_key()) == 'users.user': user = ct.get_object_for_this_type(pk=recipient_obj['recipient_id']) organization = OrganizationMembership.objects.get_primary(user).organization if not sub_matter.collaborations.filter(organization=organization).exists(): raise serializers.ValidationError({'recipients': 'Wrong user.'}) elif ".".join(ct.natural_key()) == 'contacts.contact': contact = ct.get_object_for_this_type(pk=recipient_obj['recipient_id']) if not sub_matter.contactrelation_set.filter(contact=contact).exists(): raise serializers.ValidationError({'recipients': 'Wrong contact.'}) else: raise serializers.ValidationError({'recipients': 'Wrong Content Type.'}) class CommunicationMessageSerializer(serializers.ModelSerializer): sender = UserSerializer(read_only=True) recipients = CommunicationMessageRecipientSerializer(many=True, required=False, write_only=True) email_recipients = CommunicationMessageEmailRecipientSerializer(many=True, required=False, write_only=True) thread = serializers.PrimaryKeyRelatedField(read_only=True) last_message = serializers.DateField(read_only=True) attached_files = serializers.SerializerMethodField('get_files') obj = CommunicationMessageObjectSerializer(source='sub_matter', read_only=True) class Meta: model = CommunicationMessage fields = ('id', 'sub_matter', 'event', 'subject', 'body', 'sender', 'recipients', 'parent', 'thread', 'created', 'last_message', 'files', 'obj', 'email_recipients', 'attached_files', 'private_to') def get_files(self, obj): from files.api.serializers import FileSerializer return FileSerializer(obj.files.all(), many=True, context=self.context).data def validate(self, attrs): parent = attrs.get('parent') if self.instance is None and parent is None: _validate_recipients(attrs, attrs.get('sub_matter')) return attrs def create(self, validated_data): recipients = [] if 'recipients' in validated_data: recipients = validated_data.pop('recipients') email_recipients = [] if 'email_recipients' in validated_data: email_recipients = validated_data.pop('email_recipients') instance = super(CommunicationMessageSerializer, self).create(validated_data) for recipient_obj in recipients: ct = recipient_obj['recipient_type'] if ".".join(ct.natural_key()) == 'users.user': user = ct.get_object_for_this_type(pk=recipient_obj['recipient_id']) instance.thread.user_recipients.add(user) elif ".".join(ct.natural_key()) == 'contacts.contact': contact = ct.get_object_for_this_type(pk=recipient_obj['recipient_id']) instance.thread.contact_recipients.add(contact) for recipient_obj in email_recipients: user, invitation = User.objects.get_or_invite(recipient_obj['email']) instance.thread.user_recipients.add(user) return instance