Commit df9bb01c authored by Arnaud Fabre's avatar Arnaud Fabre

updates link between representatives / votes

parent 9eaea806
......@@ -17,21 +17,21 @@ class ProposalAdmin(admin.ModelAdmin):
class NoneMatchingFilter(admin.SimpleListFilter):
title = 'Remote id'
parameter_name = 'representative_remote_id'
title = 'Representative'
parameter_name = 'representative'
def lookups(self, request, model_admin):
return [('None', 'Unknown')]
def queryset(self, request, queryset):
if self.value() == 'None':
return queryset.filter(representative_remote_id=None)
return queryset.filter(representative=None)
else:
return queryset
class VoteAdmin(admin.ModelAdmin):
list_display = ('id', 'proposal_reference', 'position', 'representative_name', 'representative_remote_id')
list_display = ('id', 'proposal_reference', 'position', 'representative', 'representative_name')
list_filter = (NoneMatchingFilter,)
def proposal_reference(self, obj):
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('representatives', '0003_auto_20150702_1827'),
('representatives_votes', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='vote',
name='representative_remote_id',
),
migrations.AddField(
model_name='vote',
name='representative',
field=models.ForeignKey(related_name='votes', to='representatives.Representative', null=True),
),
migrations.AddField(
model_name='vote',
name='representative_fingerprint',
field=models.CharField(max_length=200, blank=True),
),
migrations.AlterField(
model_name='vote',
name='representative_name',
field=models.CharField(default='', max_length=200, blank=True),
preserve_default=False,
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('representatives', '0003_auto_20150702_1827'),
('representatives_votes', '0002_auto_20150707_1611'),
]
operations = [
migrations.RemoveField(
model_name='vote',
name='representative_fingerprint',
),
migrations.AddField(
model_name='proposal',
name='representatives',
field=models.ManyToManyField(to='representatives.Representative', through='representatives_votes.Vote'),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('representatives_votes', '0003_auto_20150708_1358'),
]
operations = [
migrations.AlterModelOptions(
name='proposal',
options={'ordering': ['datetime']},
),
migrations.AlterModelOptions(
name='vote',
options={'ordering': ['proposal__datetime']},
),
migrations.AlterField(
model_name='proposal',
name='representatives',
field=models.ManyToManyField(related_name='proposals', through='representatives_votes.Vote', to='representatives.Representative'),
),
]
......@@ -18,7 +18,8 @@
from django.db import models
from representatives.models import TimeStampedModel, HashableModel
from representatives.models import TimeStampedModel, HashableModel, Representative
class Dossier(HashableModel, TimeStampedModel):
title = models.CharField(max_length=1000)
......@@ -43,10 +44,25 @@ class Proposal(HashableModel, TimeStampedModel):
total_against = models.IntegerField()
total_for = models.IntegerField()
representatives = models.ManyToManyField(
Representative, through='Vote', related_name='proposals'
)
hashable_fields = ['dossier', 'title', 'reference',
'kind', 'total_abstain', 'total_against',
'total_for']
class Meta:
ordering = ['datetime']
@property
def status(self):
if self.total_for > self.total_against:
return 'adopted'
else:
return 'rejected'
def __unicode__(self):
return unicode(self.title)
......@@ -59,9 +75,12 @@ class Vote(models.Model):
)
proposal = models.ForeignKey(Proposal, related_name='votes')
# There are two representative fields for flexibility,
representative_name = models.CharField(max_length=200, blank=True, null=True)
representative_remote_id = models.CharField(max_length=200, blank=True, null=True)
representative = models.ForeignKey(Representative, related_name='votes', null=True)
# Save representative name in case of we don't find the representative
representative_name = models.CharField(max_length=200, blank=True)
position = models.CharField(max_length=10, choices=VOTECHOICES)
class Meta:
ordering = ['proposal__datetime']
......@@ -19,23 +19,29 @@
# Copyright (C) 2015 Arnaud Fabre <af@laquadrature.net>
import representatives_votes.models as models
from representatives.models import Representative
from rest_framework import serializers
from django.db import transaction
class VoteSerializer(serializers.ModelSerializer):
"""
Vote serializer
"""
proposal = serializers.CharField(
source='proposal.fingerprint'
)
representative = serializers.CharField(
source='representative.fingerprint',
allow_null=True
)
class Meta:
model = models.Vote
fields = (
'id',
'proposal',
'representative',
'representative_name',
'representative_remote_id',
'position'
)
......@@ -44,6 +50,13 @@ class VoteSerializer(serializers.ModelSerializer):
data['proposal'] = models.Proposal.objects.get(
fingerprint=data['proposal']['fingerprint']
)
if data['representative']['fingerprint']:
data['representative'] = Representative.objects.get(
fingerprint=data['representative']['fingerprint']
)
else:
data['representative'] = None
return data
......@@ -51,6 +64,16 @@ class ProposalSerializer(serializers.ModelSerializer):
dossier = serializers.CharField(
source='dossier.fingerprint'
)
dossier_title = serializers.CharField(
source='dossier.title',
read_only=True
)
dossier_reference = serializers.CharField(
source='dossier.reference',
read_only=True
)
class Meta:
model = models.Proposal
......@@ -58,6 +81,8 @@ class ProposalSerializer(serializers.ModelSerializer):
'id',
'fingerprint',
'dossier',
'dossier_title',
'dossier_reference',
'title',
'description',
'reference',
......@@ -66,6 +91,7 @@ class ProposalSerializer(serializers.ModelSerializer):
'total_abstain',
'total_against',
'total_for',
'url',
)
def to_internal_value(self, data):
......@@ -75,14 +101,15 @@ class ProposalSerializer(serializers.ModelSerializer):
)
validated_data['votes'] = data['votes']
return validated_data
def _create_votes(self, votes_data, proposal):
for vote in votes_data:
vote['proposal'] = proposal
models.Vote.objects.create(
**vote
)
serializer = VoteSerializer(data=vote)
if serializer.is_valid():
serializer.save()
else:
raise Exception(serializer.errors)
def create(self, validated_data):
votes_data = validated_data.pop('votes')
proposal = models.Proposal.objects.create(
......@@ -100,6 +127,7 @@ class ProposalSerializer(serializers.ModelSerializer):
class ProposalDetailSerializer(ProposalSerializer):
""" Proposal serializer that includes votes """
votes = VoteSerializer(many=True)
class Meta(ProposalSerializer.Meta):
......@@ -109,6 +137,7 @@ class ProposalDetailSerializer(ProposalSerializer):
class DossierSerializer(serializers.ModelSerializer):
""" Base dossier serializer """
class Meta:
model = models.Dossier
fields = (
......@@ -123,10 +152,10 @@ class DossierSerializer(serializers.ModelSerializer):
class DossierDetailSerializer(DossierSerializer):
'''
Dossier Serializer with proposals details
'''
"""
Dossier serializer that includes proposals
and votes
"""
proposals = ProposalDetailSerializer(
many = True,
)
......
......@@ -35,7 +35,7 @@ from representatives_votes.serializers import DossierSerializer, ProposalSeriali
logger = logging.getLogger(__name__)
@shared_task
def import_a_dossier_from_toutatis(fingerprint):
'''
Import a complete dossier from a toutatis server
......@@ -54,37 +54,40 @@ def import_a_dossier_from_toutatis(fingerprint):
raise Exception('Search should return one and only one result')
detail_url = data['results'][0]['url']
data = json.load(urlopen(detail_url))
import_a_model(data, Dossier, DossierSerializer)
dossier = import_a_model(data, Dossier, DossierSerializer)
for proposal in data['proposals']:
logger.info('Import proposal {}'.format(proposal['title']))
import_a_model(proposal, Proposal, ProposalSerializer)
return dossier
@shared_task
def import_a_proposal_from_toutatis(fingerprint, delay=False):
def import_a_proposal_from_toutatis(fingerprint):
'''
Import a partial dossier from a toutatis server
'''
toutatis_server = settings.TOUTATIS_SERVER
search_url = '{server}/api/proposals/?fingerprint={fingerprint}'.format({
'server': toutatis_server,
'fingerprint': fingerprint
})
search_url = '{}/api/proposals/?fingerprint={}'.format(
toutatis_server,
fingerprint
)
logger.info('Import proposal with fingerprint {} from {}'.format(
fingerprint,
search_url
))
data = json.load(urlopen(search_url))
if data['count'] != 1:
proposal_data = json.load(urlopen(search_url))
if proposal_data['count'] != 1:
raise Exception('Search should return one and only one result')
detail_url = data['results'][0]['url']
detail_url = proposal_data['results'][0]['url']
proposal_data = json.load(urlopen(detail_url))
dossier_url = proposal_data['dossier']
dossier_data = json.load(urlopen(dossier_url))
dossier_data['proposals'] = [proposal_data]
if delay:
import_a_dossier.delay(dossier_data)
else:
import_a_dossier(dossier_data)
search_url = '{}/api/dossiers/?fingerprint={}'.format(
toutatis_server,
proposal_data['dossier']
)
dossier_data = json.load(urlopen(search_url))
if dossier_data['count'] != 1:
raise Exception('Search should return one and only one result')
import_a_model(dossier_data['results'][0], Dossier, DossierSerializer)
return import_a_model(proposal_data, Proposal, ProposalSerializer)
def export_a_dossier(dossier):
serialized = DossierDetailSerializer(dossier)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment