import mistune from django.contrib.auth import get_user_model from django_bleach.templatetags.bleach_tags import bleach_value from rest_framework import serializers from opentech.apply.activity.models import Activity from opentech.apply.determinations.views import DeterminationCreateOrUpdateView from opentech.apply.funds.models import ApplicationSubmission, RoundsAndLabs from opentech.apply.review.models import Review, ReviewOpinion from opentech.apply.review.options import RECOMMENDATION_CHOICES from opentech.apply.users.groups import PARTNER_GROUP_NAME, STAFF_GROUP_NAME User = get_user_model() markdown = mistune.Markdown() class ActionSerializer(serializers.Field): def to_representation(self, instance): actions = instance.get_actions_for_user(self.context['request'].user) representation = [] for transition, action in actions: action_dict = { 'value': transition, 'display': action } # Sometimes the status does not exist in the # determination matrix. try: redirect = DeterminationCreateOrUpdateView.should_redirect( None, instance, transition, ) except KeyError: redirect = None if redirect: action_dict['type'] = 'redirect' action_dict['target'] = redirect.url else: action_dict['type'] = 'submit' representation.append(action_dict) return representation class OpinionSerializer(serializers.ModelSerializer): author_id = serializers.ReadOnlyField(source='author.id') opinion = serializers.ReadOnlyField(source='get_opinion_display') class Meta: model = ReviewOpinion fields = ('author_id', 'opinion') class ReviewSerializer(serializers.ModelSerializer): author_id = serializers.ReadOnlyField(source='author.id') url = serializers.ReadOnlyField(source='get_absolute_url') opinions = OpinionSerializer(read_only=True, many=True) recommendation = serializers.SerializerMethodField() score = serializers.ReadOnlyField(source='get_score_display') class Meta: model = Review fields = ('id', 'score', 'author_id', 'url', 'opinions', 'recommendation') def get_recommendation(self, obj): return { 'value': obj.recommendation, 'display': obj.get_recommendation_display(), } class ReviewSummarySerializer(serializers.Serializer): reviews = ReviewSerializer(many=True, read_only=True) count = serializers.ReadOnlyField(source='reviews.count') score = serializers.ReadOnlyField(source='reviews.score') recommendation = serializers.SerializerMethodField() assigned = serializers.SerializerMethodField() def get_recommendation(self, obj): recommendation = obj.reviews.recommendation() return { 'value': recommendation, 'display': dict(RECOMMENDATION_CHOICES).get(recommendation), } def get_assigned(self, obj): assigned_reviewers = obj.assigned.select_related('reviewer', 'role', 'type') response = [ { 'id': assigned.id, 'name': str(assigned.reviewer), 'role': { 'icon': assigned.role and assigned.role.icon_url('fill-12x12'), 'name': assigned.role and assigned.role.name, 'order': assigned.role and assigned.role.order, }, 'is_staff': assigned.type.name == STAFF_GROUP_NAME, 'is_partner': assigned.type.name == PARTNER_GROUP_NAME, } for assigned in assigned_reviewers ] return response class TimestampField(serializers.Field): def to_representation(self, value): return value.timestamp() * 1000 class SubmissionListSerializer(serializers.ModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='api:v1:submissions:detail') round = serializers.SerializerMethodField() last_update = TimestampField() class Meta: model = ApplicationSubmission fields = ('id', 'title', 'status', 'url', 'round', 'last_update') def get_round(self, obj): """ This gets round or lab ID. """ return obj.round_id or obj.page_id class SubmissionDetailSerializer(serializers.ModelSerializer): questions = serializers.SerializerMethodField() meta_questions = serializers.SerializerMethodField() stage = serializers.CharField(source='stage.name') actions = ActionSerializer(source='*') review = ReviewSummarySerializer(source='*') phase = serializers.CharField() screening = serializers.ReadOnlyField(source='screening_status.title') class Meta: model = ApplicationSubmission fields = ('id', 'title', 'stage', 'status', 'phase', 'meta_questions', 'questions', 'actions', 'review', 'screening') def serialize_questions(self, obj, fields): for field_id in fields: yield obj.serialize(field_id) def get_meta_questions(self, obj): meta_questions = { 'title': 'Project Name', 'full_name': 'Legal Name', 'email': 'Email', 'value': 'Requested Funding', 'duration': 'Project Duration', 'address': 'Address' } data = self.serialize_questions(obj, obj.named_blocks.values()) data = [ { **response, 'question': meta_questions.get(response['type'], response['question']) } for response in data ] return data def get_questions(self, obj): return self.serialize_questions(obj, obj.normal_blocks) class SubmissionActionSerializer(serializers.ModelSerializer): actions = ActionSerializer(source='*', read_only=True) class Meta: model = ApplicationSubmission fields = ('id', 'actions') class RoundLabDetailSerializer(serializers.ModelSerializer): workflow = serializers.SerializerMethodField() class Meta: model = RoundsAndLabs fields = ('id', 'title', 'workflow') def get_workflow(self, obj): return [ { 'value': phase.name, 'display': phase.display_name } for phase in obj.workflow.values() ] class RoundLabSerializer(serializers.ModelSerializer): class Meta: model = RoundsAndLabs fields = ('id', 'title') class CommentSerializer(serializers.ModelSerializer): user = serializers.StringRelatedField() message = serializers.SerializerMethodField() edit_url = serializers.HyperlinkedIdentityField(view_name='api:v1:comments:edit') editable = serializers.SerializerMethodField() timestamp = TimestampField(read_only=True) edited = TimestampField(read_only=True) class Meta: model = Activity fields = ('id', 'timestamp', 'user', 'source', 'message', 'visibility', 'edited', 'edit_url', 'editable') def get_message(self, obj): return bleach_value(markdown(obj.message)) def get_editable(self, obj): return self.context['request'].user == obj.user class CommentCreateSerializer(serializers.ModelSerializer): user = serializers.StringRelatedField() edit_url = serializers.HyperlinkedIdentityField(view_name='api:v1:comments:edit') editable = serializers.SerializerMethodField() timestamp = TimestampField(read_only=True) edited = TimestampField(read_only=True) class Meta: model = Activity fields = ('id', 'timestamp', 'user', 'message', 'visibility', 'edited', 'edit_url', 'editable') def get_editable(self, obj): return self.context['request'].user == obj.user class CommentEditSerializer(CommentCreateSerializer): class Meta(CommentCreateSerializer.Meta): read_only_fields = ('timestamp', 'visibility', 'edited',)