class Member(models.Model): name = models.CharField(max_length=64) parties = models.ManyToManyField(Party, related_name='all_members', through='Membership') current_party = models.ForeignKey(Party, related_name='members', blank=True, null=True) current_position = models.PositiveIntegerField(blank=True, default=999) start_date = models.DateField(blank=True, null=True) end_date = models.DateField(blank=True, null=True) img_url = models.URLField(blank=True) phone = models.CharField(blank=True, null=True, max_length=20) fax = models.CharField(blank=True, null=True, max_length=20) email = models.EmailField(blank=True, null=True) website = models.URLField(blank=True, null=True) family_status = models.CharField(blank=True, null=True, max_length=10) number_of_children = models.IntegerField(blank=True, null=True) date_of_birth = models.DateField(blank=True, null=True) place_of_birth = models.CharField(blank=True, null=True, max_length=100) date_of_death = models.DateField(blank=True, null=True) year_of_aliyah = models.IntegerField(blank=True, null=True) is_current = models.BooleanField(default=True, db_index=True) blog = models.OneToOneField(Blog, blank=True, null=True) place_of_residence = models.CharField( blank=True, null=True, max_length=100, help_text=_('an accurate place of residence (for example, an address')) area_of_residence = models.CharField( blank=True, null=True, max_length=100, help_text=_('a general area of residence (for example, "the negev"')) place_of_residence_lat = models.CharField(blank=True, null=True, max_length=16) place_of_residence_lon = models.CharField(blank=True, null=True, max_length=16) residence_centrality = models.IntegerField(blank=True, null=True) residence_economy = models.IntegerField(blank=True, null=True) user = models.ForeignKey(User, blank=True, null=True) gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True, null=True) current_role_descriptions = models.CharField(blank=True, null=True, max_length=1024) bills_stats_proposed = models.IntegerField(default=0) bills_stats_pre = models.IntegerField(default=0) bills_stats_first = models.IntegerField(default=0) bills_stats_approved = models.IntegerField(default=0) average_weekly_presence_hours = models.FloatField(null=True, blank=True) average_monthly_committee_presence = models.FloatField(null=True, blank=True) backlinks_enabled = models.BooleanField(default=True) @property def ok_url(self): return OK_BASE_URL + "/member/" + str(self.id) objects = BetterManager() current_knesset = CurrentKnessetMembersManager() #added by kikar-hamedina persona = generic.GenericRelation(Facebook_Persona) @property def facebook_persona(self): return self.persona.select_related().first() class Meta: ordering = ['name'] verbose_name = _('Member') verbose_name_plural = _('Members') def __unicode__(self): return self.name def save(self, **kwargs): self.recalc_average_monthly_committee_presence() super(Member, self).save(**kwargs) def average_votes_per_month(self): return self.voting_statistics.average_votes_per_month() def is_female(self): return self.gender == 'F' def title(self): return self.name def name_with_dashes(self): return self.name.replace(' - ', ' ').replace("'", "").replace( u"”", '').replace("`", "").replace("(", "").replace(")", "").replace( u'\xa0', ' ').replace(' ', '-') def Party(self): return self.parties.all().order_by('-membership__start_date')[0] def PartiesString(self): return ", ".join([ p.NameWithLink() for p in self.parties.all().order_by('membership__start_date') ]) PartiesString.allow_tags = True def party_at(self, date): """Returns the party this memeber was at given date """ memberships = Membership.objects.filter(member=self) for membership in memberships: if (not membership.start_date or membership.start_date <= date) and\ (not membership.end_date or membership.end_date >= date): return membership.party return None def TotalVotesCount(self): return self.votes.exclude(voteaction__type='no-vote').count() def for_votes(self): return self.votes.filter(voteaction__type='for') def ForVotesCount(self): return self.for_votes().count() def against_votes(self): return self.votes.filter(voteaction__type='against') def AgainstVotesCount(self): return self.against_votes().count() def abstain_votes(self): return self.votes.filter(voteaction__type='abstain') def AbstainVotesCount(self): return self.abstain_votes().count() def no_votes(self): return self.votes.filter(voteaction__type='no-vote') def NoVotesCount(self): return self.no_votes().count() def LowestCorrelations(self): return Correlation.objects.filter( m1=self.id).order_by('normalized_score')[0:4] def HighestCorrelations(self): return Correlation.objects.filter( m1=self.id).order_by('-normalized_score')[0:4] def CorrelationListToString(self, cl): strings = [] for c in cl: if c.m1 == self: m = c.m2 else: m = c.m1 strings.append("%s (%.0f)" % (m.NameWithLink(), 100 * c.normalized_score)) return ", ".join(strings) def service_time(self): """returns the number of days this MK has been serving in the current knesset """ if not self.start_date: return 0 d = Knesset.objects.current_knesset().start_date start_date = max(self.start_date, d) if self.is_current: end_date = date.today() else: try: end_date = self.end_date except TypeError: logger.warn( 'MK %d is not current, but missing end or start date' % self.id) return None return (end_date - start_date).days def average_weekly_presence(self): d = Knesset.objects.current_knesset().start_date hours = WeeklyPresence.objects.filter( date__gt=d, member=self).values_list('hours', flat=True) if len(hours): return round(sum(hours) / len(hours), 1) else: return None def committee_meetings_per_month(self): d = Knesset.objects.current_knesset().start_date service_time = self.service_time() if not service_time or not self.id: return 0 return round( self.committee_meetings.filter(date__gt=d).count() * 30.0 / service_time, 2) @models.permalink def get_absolute_url(self): return ('member-detail-with-slug', [str(self.id), self.name_with_dashes()]) def NameWithLink(self): return '<a href="%s">%s</a>' % (self.get_absolute_url(), self.name) NameWithLink.allow_tags = True @property def get_role(self): if self.current_role_descriptions: return self.current_role_descriptions if self.is_current: if self.is_female(): if self.current_party.is_coalition: return ugettext('Coalition Member (female)') else: return ugettext('Opposition Member (female)') else: if self.current_party.is_coalition: return ugettext('Coalition Member (male)') else: return ugettext('Opposition Member (male)') if self.is_female(): return ugettext('Past Member (female)') else: return ugettext('Past Member (male)') @property def roles(self): """Roles list (splitted by pipe)""" return [x.strip() for x in self.get_role.split('|')] @property def committees(self): """Committee list (splitted by comma)""" return [x.strip() for x in self.committees.split(',')] @property def is_minister(self): """Check if one of the roles starts with minister""" # TODO Once we have roles table change this minister = ugettext('Minister') return any(x.startswith(minister) for x in self.roles) @property def coalition_status(self): """Current Coalition/Opposition member, or past member. Good for usage with Django's yesno filters :returns: True - Coalition, False - Opposition, None: Past member """ if not self.is_current: return None return self.current_party.is_coalition def recalc_bill_statistics(self): d = Knesset.objects.current_knesset().start_date self.bills_stats_proposed = self.proposals_proposed.filter( date__gte=d).count() self.bills_stats_pre = self.proposals_proposed.filter( date__gte=d, bill__stage__in=['2', '3', '4', '5', '6']).count() self.bills_stats_first = self.proposals_proposed.filter( date__gte=d, bill__stage__in=['4', '5', '6']).count() self.bills_stats_approved = self.proposals_proposed.filter( date__gte=d, bill__stage='6').count() self.save() def recalc_average_weekly_presence_hours(self): self.average_weekly_presence_hours = self.average_weekly_presence() self.save() def recalc_average_monthly_committee_presence(self): self.average_monthly_committee_presence = self.committee_meetings_per_month( ) @property def names(self): names = [self.name] for altname in self.memberaltname_set.all(): names.append(altname.name) return names # def get_agendas_values(self): # from agendas.models import Agenda # # out = {} # for agenda_id, mks in Agenda.objects.get_mks_values().items(): # try: # out[agenda_id] = dict(mks)[self.id] # except KeyError: # pass # return out @property def firstname(self): """return the first name of the member""" return self.name.split()[0] @property def highres_img_url(self): "Get higher res image for the member" # TODO a hack for now, change later for url field if not self.img_url: return self.img_url return self.img_url.replace('-s.jpg', '.jpg') @property def age(self): return relativedelta(date.today(), self.date_of_birth)
class Party(models.Model): name = models.CharField(max_length=64) start_date = models.DateField(blank=True, null=True) end_date = models.DateField(blank=True, null=True) is_coalition = models.BooleanField(default=False) number_of_members = models.IntegerField(blank=True, null=True) number_of_seats = models.IntegerField(blank=True, null=True) knesset = models.ForeignKey(Knesset, related_name='parties', db_index=True, null=True, blank=True) logo = models.ImageField(blank=True, null=True, upload_to='partyLogos') objects = BetterManager() current_knesset = CurrentKnessetPartyManager() class Meta: verbose_name = _('Party') verbose_name_plural = _('Parties') ordering = ('-number_of_seats', ) unique_together = ('knesset', 'name') @property def uri_template(self): # TODO: use the Site's url from django.contrib.site return "%s/api/party/%s/htmldiv/" % ('', self.id) @property def ok_url(self): return OK_BASE_URL + "/party/" + str(self.id) def __unicode__(self): if self.is_current: return self.name return _(u'%(name)s in Knesset %(number)d') % { 'name': self.name, 'number': self.knesset.number if self.knesset else 0 } def current_members(self): # for current knesset, we want to display by selecting is_current, # for older ones, it's not relevant if self.knesset == Knesset.objects.current_knesset(): return self.members.filter( is_current=True).order_by('current_position') else: return self.all_members.order_by('current_position') def past_members(self): return self.members.filter(is_current=False) def name_with_dashes(self): return self.name.replace("'", '"').replace(' ', '-') def Url(self): return "/admin/simple/party/%d" % self.id def NameWithLink(self): return '<a href="%s">%s</a>' % (self.get_absolute_url(), self.name) NameWithLink.allow_tags = True def MembersString(self): return ", ".join( [m.NameWithLink() for m in self.members.all().order_by('name')]) MembersString.allow_tags = True def member_list(self): return self.members.all() def is_coalition_at(self, date): """Returns true is this party was a part of the coalition at the given date""" memberships = CoalitionMembership.objects.filter(party=self) for membership in memberships: if (not membership.start_date or membership.start_date <= date) and\ (not membership.end_date or membership.end_date >= date): return True return False # Changed for kikar-integration!! original - reverse 'party-details' @models.permalink def get_absolute_url(self): return ('party', [str(self.id)]) def get_affiliation(self): return _('Coalition') if self.is_coalition else _('Opposition') @property def is_current(self): return self.knesset == Knesset.objects.current_knesset()
class Member(models.Model): id = models.IntegerField( primary_key=True, help_text= "Pay attention that the value of this field must correspond to the official Knesset member id" ) name = models.CharField(max_length=64) parties = models.ManyToManyField('Party', related_name='all_members', through='Membership') current_party = models.ForeignKey('Party', related_name='members', blank=True, null=True) current_position = models.PositiveIntegerField(blank=True, default=999) start_date = models.DateField(blank=True, null=True) end_date = models.DateField(blank=True, null=True) img_url = models.URLField(blank=True) phone = models.CharField(blank=True, null=True, max_length=20) fax = models.CharField(blank=True, null=True, max_length=20) email = models.EmailField(blank=True, null=True) website = models.URLField(blank=True, null=True) family_status = models.CharField(blank=True, null=True, max_length=10) number_of_children = models.IntegerField(blank=True, null=True) date_of_birth = models.DateField(blank=True, null=True) place_of_birth = models.CharField(blank=True, null=True, max_length=100) date_of_death = models.DateField(blank=True, null=True) year_of_aliyah = models.IntegerField(blank=True, null=True) is_current = models.BooleanField(default=True, db_index=True) blog = models.OneToOneField(Blog, blank=True, null=True) place_of_residence = models.CharField( blank=True, null=True, max_length=100, help_text=_('an accurate place of residence (for example, an address')) area_of_residence = models.CharField( blank=True, null=True, max_length=100, help_text=_('a general area of residence (for example, "the negev"')) place_of_residence_lat = models.CharField(blank=True, null=True, max_length=16) place_of_residence_lon = models.CharField(blank=True, null=True, max_length=16) residence_centrality = models.IntegerField(blank=True, null=True) residence_economy = models.IntegerField(blank=True, null=True) user = models.ForeignKey(User, blank=True, null=True) gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True, null=True) current_role_descriptions = models.CharField(blank=True, null=True, max_length=1024) bills_stats_proposed = models.IntegerField(default=0) bills_stats_pre = models.IntegerField(default=0) bills_stats_first = models.IntegerField(default=0) bills_stats_approved = models.IntegerField(default=0) average_weekly_presence_hours = models.FloatField(null=True, blank=True) average_monthly_committee_presence = models.FloatField(null=True, blank=True) backlinks_enabled = models.BooleanField(default=True) objects = BetterManager() current_knesset = CurrentKnessetMembersManager() current_members = CurrentKnessetActiveMembersManager() class Meta: ordering = ['name'] verbose_name = _('Member') verbose_name_plural = _('Members') def __unicode__(self): return self.name def save(self, **kwargs): self.recalc_average_monthly_committee_presence() if self.id is None: try: max_id = Member.objects.all().aggregate(Max('id'))['id__max'] if max_id is None: max_id = 0 except: max_id = 0 max_id += 1 self.id = max_id super(Member, self).save(**kwargs) def average_votes_per_month(self): return self.voting_statistics.average_votes_per_month() def is_female(self): return self.gender == 'F' def title(self): return self.name def name_with_dashes(self): return self.name.replace(' - ', ' ').replace("'", "").replace( u"”", '').replace("`", "").replace("(", "").replace(")", "").replace( u'\xa0', ' ').replace(' ', '-') def Party(self): return self.parties.all().order_by('-membership__start_date')[0] def PartiesString(self): return ", ".join([ p.NameWithLink() for p in self.parties.all().order_by('membership__start_date') ]) PartiesString.allow_tags = True def party_at(self, date): """Returns the party this memeber was at given date """ # make sure date is not a datetime object if isinstance(date, datetime.datetime): date = datetime.date(date.year, date.month, date.day) memberships = Membership.objects.filter( member=self).order_by('-start_date') for membership in memberships: if (not membership.start_date or membership.start_date <= date) and \ (not membership.end_date or membership.end_date >= date): return membership.party return None def TotalVotesCount(self): return self.votes.exclude(voteaction__type='no-vote').count() def for_votes(self): return self.votes.filter(voteaction__type='for') def ForVotesCount(self): return self.for_votes().count() def against_votes(self): return self.votes.filter(voteaction__type='against') def AgainstVotesCount(self): return self.against_votes().count() def abstain_votes(self): return self.votes.filter(voteaction__type='abstain') def AbstainVotesCount(self): return self.abstain_votes().count() def no_votes(self): return self.votes.filter(voteaction__type='no-vote') def NoVotesCount(self): return self.no_votes().count() def LowestCorrelations(self): return Correlation.objects.filter( m1=self.id).order_by('normalized_score')[0:4] def HighestCorrelations(self): return Correlation.objects.filter( m1=self.id).order_by('-normalized_score')[0:4] def CorrelationListToString(self, cl): strings = [] for c in cl: if c.m1 == self: m = c.m2 else: m = c.m1 strings.append("%s (%.0f)" % (m.NameWithLink(), 100 * c.normalized_score)) return ", ".join(strings) def service_time(self): """returns the number of days this MK has been serving in the current knesset """ if not self.start_date: return 0 d = Knesset.objects.current_knesset().start_date start_date = max(self.start_date, d) if self.is_current: end_date = date.today() else: end_date = self.end_date if not end_date: logger.warn('MK %d is not current, but end date is None' % self.id) return None return (end_date - start_date).days def average_weekly_presence(self): d = Knesset.objects.current_knesset().start_date hours = WeeklyPresence.objects.filter( date__gt=d, member=self).values_list('hours', flat=True) if len(hours): return round(sum(hours) / len(hours), 1) else: return None def committee_meetings_per_month(self): service_time = self.service_time() if not service_time or not self.id: return 0 return round( self.total_meetings_count_current_knesset * 30.0 / service_time, 2) def committee_meeting_current_knesset(self): d = Knesset.objects.current_knesset().start_date return self.committee_meetings.filter(date__gte=d) @property def participated_in_committees_for_current_knesset(self): committee_meetings = list(self.committee_meeting_current_knesset()) committees = set() for committee, meetings in itertools.groupby( committee_meetings, lambda x: x.committee.name): committees.add(committee) return committees def total_meetings_count_for_committee(self, committee_name): return self.committee_meeting_current_knesset().filter( committee__name=committee_name).count() def get_active_committees(self): return itertools.chain( self.committees.exclude(hide=True), self.chaired_committees.exclude(hide=True), ) @property def total_meetings_count_current_knesset(self): return self.committee_meeting_current_knesset().count() @models.permalink def get_absolute_url(self): return ('member-detail-with-slug', [str(self.id), self.name_with_dashes()]) def get_current_knesset_bills_by_stage_url(self, stage): current_knesset = Knesset.objects.current_knesset() return utils.reverse_with_query('bill-list', query_kwargs={ 'member': self.id, 'knesset_id': current_knesset.number, 'stage': stage }) def NameWithLink(self): return '<a href="%s">%s</a>' % (self.get_absolute_url(), self.name) NameWithLink.allow_tags = True @property def get_role(self): if self.current_role_descriptions: return self.current_role_descriptions return self.get_gender_aware_mk_role_description() def get_gender_aware_mk_role_description(self): if self.is_current: if self.is_female(): if self.current_party.is_coalition: return _('Coalition Member (female)') else: return _('Opposition Member (female)') else: if self.current_party.is_coalition: return _('Coalition Member (male)') else: return _('Opposition Member (male)') if self.is_female(): return _('Past Member (female)') else: return _('Past Member (male)') @property def roles(self): """Roles list (splitted by pipe)""" return [x.strip() for x in self.get_role.split('|')] @property def is_minister(self): """Check if one of the roles starts with minister""" # TODO Once we have roles table change this minister = _('Minister') return any(x.startswith(minister) for x in self.roles) @property def coalition_status(self): """Current Coalition/Opposition member, or past member. Good for usage with Django's yesno filters :returns: True - Coalition, False - Opposition, None: Past member """ if not self.is_current: return None return self.current_party.is_coalition def recalc_bill_statistics(self): if waffle.switch_is_active('use_old_statistics'): self._calc_bill_statistics_by_bill_stage_date() else: self._calc_bill_statistics_by_proposal_dates() def _calc_bill_statistics_by_proposal_dates(self): current_knesset = Knesset.objects.current_knesset() knesset_range = current_knesset.start_date, current_knesset.end_date or date.today( ) member_bills = self.bills.get_bills_by_private_proposal_date_for_member( knesset_range, member=self) self.bills_stats_proposed = member_bills.count() self.bills_stats_pre = member_bills.filter(stage__in=[ BillStages.PRE_APPROVED, BillStages.IN_COMMITTEE, BillStages. FIRST_VOTE, BillStages.COMMITTEE_CORRECTIONS, BillStages.APPROVED, BillStages.FAILED_FIRST_VOTE, BillStages.FAILED_APPROVAL ]).count() self.bills_stats_first = member_bills.filter(stage__in=[ BillStages.FIRST_VOTE, BillStages.COMMITTEE_CORRECTIONS, BillStages.APPROVED, BillStages.FAILED_APPROVAL ]).count() self.bills_stats_approved = member_bills.filter( stage=BillStages.APPROVED).count() self.save() def _calc_bill_statistics_by_bill_stage_date(self): # Deprecated method, here to allow reverting if needed d = Knesset.objects.current_knesset().start_date self.bills_stats_proposed = self.bills.filter( stage_date__gte=d).count() self.bills_stats_pre = self.bills.filter( stage_date__gte=d, stage__in=[ BillStages.PRE_APPROVED, BillStages.IN_COMMITTEE, BillStages.FIRST_VOTE, BillStages.COMMITTEE_CORRECTIONS, BillStages.APPROVED, BillStages.FAILED_FIRST_VOTE, BillStages.FAILED_APPROVAL ]).count() self.bills_stats_first = self.bills.filter( stage_date__gte=d, stage__in=[ BillStages.FIRST_VOTE, BillStages.COMMITTEE_CORRECTIONS, BillStages.APPROVED, BillStages.FAILED_APPROVAL ]).count() self.bills_stats_approved = self.bills.filter( stage_date__gte=d, stage=BillStages.APPROVED).count() self.save() def recalc_average_weekly_presence_hours(self): self.average_weekly_presence_hours = self.average_weekly_presence() self.save() def recalc_average_monthly_committee_presence(self): self.average_monthly_committee_presence = self.committee_meetings_per_month( ) @property def names(self): names = [self.name] for altname in self.memberaltname_set.all(): names.append(altname.name) return names def get_agendas_values(self): from agendas.models import Agenda out = {} for agenda_id, mks in Agenda.objects.get_mks_values().items(): try: out[agenda_id] = dict(mks)[self.id] except KeyError: pass return out @property def firstname(self): """return the first name of the member""" return self.name.split()[0] @property def highres_img_url(self): "Get higher res image for the member" # TODO a hack for now, change later for url field if not self.img_url: return self.img_url return self.img_url.replace('-s.jpg', '.jpg') @property def age(self): return relativedelta(date.today(), self.date_of_birth) @property def awards(self): return self.awards_and_convictions.filter(award_type__valence__gt=0) @property def convictions(self): return self.awards_and_convictions.filter(award_type__valence__lt=0)