diff --git a/memopol/api.py b/memopol/api.py index 6a1fd8637445a98bb9848713e5bc82559acc19c5..2986d2afba16ca9323dca8b6603f8117f3ea5ae4 100644 --- a/memopol/api.py +++ b/memopol/api.py @@ -14,6 +14,7 @@ from representatives_votes.api import ( ) from representatives_recommendations.api import ( + DossierScoreViewSet, RecommendationViewSet, RepresentativeScoreViewSet, ScoredVoteViewSet @@ -24,6 +25,7 @@ router = routers.DefaultRouter() router.register(r'constituencies', ConstituencyViewSet) router.register(r'dossiers', DossierViewSet) +router.register(r'dossier_scores', DossierScoreViewSet) router.register(r'groups', GroupViewSet) router.register(r'mandates', MandateViewSet) router.register(r'proposals', ProposalViewSet) diff --git a/representatives_recommendations/api.py b/representatives_recommendations/api.py index 3ca026b766299abf5b04d74f25e2e61b0011d4c5..8b4fa19153356c30f7ba2a6a35a9a07cf8b308f0 100644 --- a/representatives_recommendations/api.py +++ b/representatives_recommendations/api.py @@ -6,18 +6,42 @@ from rest_framework import ( from representatives.api import DefaultWebPagination from .models import ( + DossierScore, Recommendation, RepresentativeScore, ScoredVote ) from .serializers import ( + DossierScoreSerializer, RecommendationSerializer, RepresentativeScoreSerializer, ScoredVoteSerializer ) +class DossierScoreViewSet(viewsets.ReadOnlyModelViewSet): + """ + API endpoint to view representative score contribution for each dossier + """ + queryset = DossierScore.objects.all() + filter_backends = ( + filters.DjangoFilterBackend, + filters.SearchFilter, + filters.OrderingFilter + ) + filter_fields = { + 'id': ['exact'], + 'dossier': ['exact'], + 'representative': ['exact'], + 'score': ['exact', 'gte', 'lte'] + } + search_fields = ('dossier', 'representative') + ordering_fields = ('representative', 'dossier') + pagination_class = DefaultWebPagination + serializer_class = DossierScoreSerializer + + class RecommendationViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint that allows recommendations to be viewed. diff --git a/representatives_recommendations/migrations/0002_dossierscore.py b/representatives_recommendations/migrations/0002_dossierscore.py new file mode 100644 index 0000000000000000000000000000000000000000..72ebd2cd277c24a5f08c0cd417943940d5dd085b --- /dev/null +++ b/representatives_recommendations/migrations/0002_dossierscore.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('representatives_recommendations', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='DossierScore', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('score', models.IntegerField(default=0)), + ], + options={ + 'db_table': 'representatives_recommendations_dossierscores', + 'managed': False, + }, + ), + migrations.RunSQL( + """ + CREATE VIEW "representatives_recommendations_dossierscores" + AS SELECT + "representatives_votes_vote"."representative_id" || ':' || "representatives_votes_proposal"."dossier_id" AS "id", + "representatives_votes_vote"."representative_id", + "representatives_votes_proposal"."dossier_id", + SUM(CASE WHEN "representatives_votes_vote"."position" = ("representatives_recommendations_recommendation"."recommendation") + THEN "representatives_recommendations_recommendation"."weight" + ELSE (0 - "representatives_recommendations_recommendation"."weight") + END) AS "score" + FROM "representatives_votes_vote" + INNER JOIN "representatives_votes_proposal" + ON ( "representatives_votes_vote"."proposal_id" = "representatives_votes_proposal"."id" ) + LEFT OUTER JOIN "representatives_recommendations_recommendation" + ON ( "representatives_votes_proposal"."id" = "representatives_recommendations_recommendation"."proposal_id" ) + WHERE "representatives_recommendations_recommendation"."id" IS NOT NULL + GROUP BY + "representatives_votes_vote"."representative_id", + "representatives_votes_proposal"."dossier_id" + """ + ), + ] diff --git a/representatives_recommendations/models.py b/representatives_recommendations/models.py index 3f92d639de7b161947bcc28d5815271f5644a906..49a6ecf59c999f0f2102972bd39985cf3e60c609 100644 --- a/representatives_recommendations/models.py +++ b/representatives_recommendations/models.py @@ -11,6 +11,18 @@ from representatives_votes.models import Dossier, Proposal, Vote from representatives.models import Representative +class DossierScore(models.Model): + id = models.CharField(max_length=255, primary_key=True) + representative = models.ForeignKey(Representative, + on_delete=models.DO_NOTHING) + dossier = models.ForeignKey(Dossier, on_delete=models.DO_NOTHING) + score = models.IntegerField(default=0) + + class Meta: + managed = False + db_table = 'representatives_recommendations_dossierscores' + + class RepresentativeScore(models.Model): representative = models.OneToOneField('representatives.representative', primary_key=True, related_name='score') diff --git a/representatives_recommendations/serializers.py b/representatives_recommendations/serializers.py index df42c26ebd6031579074d45f3774e1d34ff73bc1..4a1ae0d0dc5fb94720d32bcd00a273ecb4969299 100644 --- a/representatives_recommendations/serializers.py +++ b/representatives_recommendations/serializers.py @@ -1,12 +1,20 @@ from rest_framework import serializers from .models import ( + DossierScore, Recommendation, RepresentativeScore, ScoredVote ) +class DossierScoreSerializer(serializers.HyperlinkedModelSerializer): + + class Meta: + model = DossierScore + fields = ('representative', 'dossier', 'score') + + class RecommendationSerializer(serializers.HyperlinkedModelSerializer): class Meta: