diff --git a/memopol/api.py b/memopol/api.py index 2986d2afba16ca9323dca8b6603f8117f3ea5ae4..40ae7fc6a33ed651a5ecea45fa0ed2817e7f585e 100644 --- a/memopol/api.py +++ b/memopol/api.py @@ -17,7 +17,7 @@ from representatives_recommendations.api import ( DossierScoreViewSet, RecommendationViewSet, RepresentativeScoreViewSet, - ScoredVoteViewSet + VoteScoreViewSet ) @@ -32,5 +32,5 @@ router.register(r'proposals', ProposalViewSet) router.register(r'recommendations', RecommendationViewSet) router.register(r'representatives', RepresentativeViewSet) router.register(r'scores', RepresentativeScoreViewSet) -router.register(r'scored_votes', ScoredVoteViewSet) +router.register(r'vote_scores', VoteScoreViewSet) router.register(r'votes', VoteViewSet) diff --git a/memopol/views.py b/memopol/views.py index e0f26602bcd345bc3ce32d00f2381e881bdfa6d7..9e0c6e3dba284fd2843b33eecdc50faf97a3bc46 100644 --- a/memopol/views.py +++ b/memopol/views.py @@ -7,7 +7,7 @@ from representatives.models import Representative from representatives_votes import views as representatives_votes_views from representatives_votes.models import Dossier, Proposal from representatives_positions.forms import PositionForm -from representatives_recommendations.models import ScoredVote +from representatives_recommendations.models import VoteScore class RepresentativeList( @@ -42,7 +42,7 @@ class RepresentativeDetail(representatives_views.RepresentativeDetail): def get_queryset(self): qs = super(RepresentativeDetail, self).get_queryset() - votes = ScoredVote.objects.filter( + votes = VoteScore.objects.filter( proposal__in=Proposal.objects.exclude(recommendation=None), ).select_related('proposal__recommendation') qs = qs.prefetch_related(models.Prefetch('votes', queryset=votes)) diff --git a/representatives_recommendations/api.py b/representatives_recommendations/api.py index f33575b92cc9e8f5aa3aff3d6937990fef450448..4d035c26a02fe451401ecb05436425dcc325c53b 100644 --- a/representatives_recommendations/api.py +++ b/representatives_recommendations/api.py @@ -9,14 +9,14 @@ from .models import ( DossierScore, Recommendation, RepresentativeScore, - ScoredVote + VoteScore ) from .serializers import ( DossierScoreSerializer, RecommendationSerializer, RepresentativeScoreSerializer, - ScoredVoteSerializer + VoteScoreSerializer ) @@ -85,12 +85,12 @@ class RepresentativeScoreViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = RepresentativeScoreSerializer -class ScoredVoteViewSet(viewsets.ReadOnlyModelViewSet): +class VoteScoreViewSet(viewsets.ReadOnlyModelViewSet): """ API endpoint to view votes with their score impact. This endpoint only shows votes that have a matching recommendation. """ - queryset = ScoredVote.objects.select_related( + queryset = VoteScore.objects.select_related( 'representative', 'proposal', 'proposal__dossier', @@ -112,4 +112,4 @@ class ScoredVoteViewSet(viewsets.ReadOnlyModelViewSet): } pagination_class = DefaultWebPagination - serializer_class = ScoredVoteSerializer + serializer_class = VoteScoreSerializer diff --git a/representatives_recommendations/migrations/0003_votescore.py b/representatives_recommendations/migrations/0003_votescore.py new file mode 100644 index 0000000000000000000000000000000000000000..7fee085cf371c5afbb805b2d9f07f2a11f841e82 --- /dev/null +++ b/representatives_recommendations/migrations/0003_votescore.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('representatives_recommendations', '0002_dossierscore'), + ] + + operations = [ + migrations.CreateModel( + name='VoteScore', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('position', models.CharField(max_length=10)), + ('score', models.IntegerField(default=0)), + ], + options={ + 'ordering': ['proposal__datetime'], + 'db_table': 'representatives_recommendations_votescores', + 'managed': False, + }, + ), + migrations.DeleteModel( + name='ScoredVote', + ), + migrations.RunSQL( + """ + CREATE VIEW "representatives_recommendations_votescores" + AS SELECT + "representatives_votes_vote"."id", + "representatives_votes_vote"."position", + "representatives_votes_vote"."proposal_id", + "representatives_votes_vote"."representative_id", + 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 + """ + ) + ] diff --git a/representatives_recommendations/models.py b/representatives_recommendations/models.py index 49a6ecf59c999f0f2102972bd39985cf3e60c609..89c042c6bacc551456d072992b88f23d4a312b00 100644 --- a/representatives_recommendations/models.py +++ b/representatives_recommendations/models.py @@ -1,7 +1,6 @@ # coding: utf-8 from django.db import models from django.db.models.signals import post_save -from django.utils.functional import cached_property from representatives_votes.contrib.parltrack.import_votes import \ vote_pre_import @@ -23,6 +22,20 @@ class DossierScore(models.Model): db_table = 'representatives_recommendations_dossierscores' +class VoteScore(models.Model): + proposal = models.ForeignKey(Proposal, related_name='votescores') + + representative = models.ForeignKey( + Representative, related_name='votescores', null=True) + position = models.CharField(max_length=10) + score = models.IntegerField(default=0) + + class Meta: + managed = False + ordering = ['proposal__datetime'] + db_table = 'representatives_recommendations_votescores' + + class RepresentativeScore(models.Model): representative = models.OneToOneField('representatives.representative', primary_key=True, related_name='score') @@ -44,20 +57,6 @@ class Recommendation(models.Model): ordering = ['proposal__datetime'] -class ScoredVote(Vote): - class Meta: - proxy = True - - @cached_property - def absolute_score(self): - recommendation = self.proposal.recommendation - - if self.position == recommendation.recommendation: - return recommendation.weight - else: - return -recommendation.weight - - def skip_votes(sender, vote_data=None, **kwargs): dossiers = getattr(sender, 'memopol_filters', None) @@ -94,9 +93,9 @@ def calculate_representative_score(representative): proposal__recommendation=None ).select_related('proposal__recommendation') - votes = ScoredVote.objects.filter(pk__in=votes.values_list('pk')) + votes = VoteScore.objects.filter(pk__in=votes.values_list('pk')) for vote in votes: - score += vote.absolute_score + score += vote.score return score diff --git a/representatives_recommendations/serializers.py b/representatives_recommendations/serializers.py index 4a1ae0d0dc5fb94720d32bcd00a273ecb4969299..330e53e4424378b836bb6222d1d9b57cb0fd27e9 100644 --- a/representatives_recommendations/serializers.py +++ b/representatives_recommendations/serializers.py @@ -4,7 +4,7 @@ from .models import ( DossierScore, Recommendation, RepresentativeScore, - ScoredVote + VoteScore ) @@ -30,16 +30,8 @@ class RepresentativeScoreSerializer(serializers.HyperlinkedModelSerializer): fields = ('representative', 'score') -class ScoredVoteSerializer(serializers.HyperlinkedModelSerializer): - """ - Scored Vote serializer - """ +class VoteScoreSerializer(serializers.HyperlinkedModelSerializer): class Meta: - model = ScoredVote - fields = ( - 'proposal', - 'representative', - 'position', - 'absolute_score' - ) + model = VoteScore + fields = ('proposal', 'representative', 'position', 'score') diff --git a/templates/representatives/representative_detail.haml b/templates/representatives/representative_detail.haml index 2775cb9d5444361574f4bfbf0947358dd11052b9..94629ffda1bc816dceb3cb36c4007f2b58942510 100644 --- a/templates/representatives/representative_detail.haml +++ b/templates/representatives/representative_detail.haml @@ -34,7 +34,7 @@ %td.icon-cell = vote.position|position_icon %td.icon-cell - = vote.absolute_score|score_label + = vote.score|score_label %h2 Mandates