Exemple #1
0
def site_search(request):
    query = request.GET.get("query")
    state = request.GET.get("state")

    bills = []
    people = []
    if query:
        bills = search_bills(state=state, query=query, sort="-latest_action")

        # pagination
        page_num = int(request.GET.get("page", 1))
        bills_paginator = Paginator(bills, 20)
        try:
            bills = bills_paginator.page(page_num)
        except EmptyPage:
            raise Http404()

        # people search
        people = []
        for p in Person.objects.search(query, state=state):
            pd = person_as_dict(p)
            pd["current_state"] = jid_to_abbr(
                p.current_jurisdiction_id).upper()
            people.append(pd)

    return render(
        request,
        "public/views/search.html",
        {
            "query": query,
            "state": state,
            "bills": bills,
            "people": people
        },
    )
Exemple #2
0
def _get_random_bills():
    bills = (Bill.objects.all().filter(
        updated_at__gte=datetime.datetime.now() -
        datetime.timedelta(days=3)).select_related(
            "legislative_session", "legislative_session__jurisdiction",
            "billstatus").prefetch_related("sponsorships").order_by("?"))[:3]
    for bill in bills:
        bill.state = jid_to_abbr(bill.legislative_session.jurisdiction_id)
    return bills
def person(request, person_id):
    SPONSORED_BILLS_TO_SHOW = 4
    RECENT_VOTES_TO_SHOW = 3

    ocd_person_id = decode_uuid(person_id)
    person = get_object_or_404(
        PersonProxy.objects.prefetch_related("memberships__organization"),
        pk=ocd_person_id,
    )

    # to display district in front of district name, or not?
    district_maybe = ""

    # canonicalize the URL
    canonical_url = person.pretty_url()
    if request.path != canonical_url:
        return redirect(canonical_url, permanent=True)

    state = person.current_role["state"]
    if not state:
        #  this breaks if they held office in two states, but we don't really worry about that
        for m in person.memberships.all():
            if m.organization.classification in ("upper", "lower",
                                                 "legislature"):
                state = jid_to_abbr(m.organization.jurisdiction_id)
        retired = True
    else:
        retired = False
        # does it start with a number?
        if str(person.current_role["district"])[0] in "0123456789":
            district_maybe = "District"
    person.all_contact_details = person.contact_details.order_by("note")

    person.sponsored_bills = list(Bill.objects.all().select_related(
        "legislative_session", "legislative_session__jurisdiction",
        "billstatus").filter(sponsorships__person=person).order_by(
            "-created_at", "id")[:SPONSORED_BILLS_TO_SHOW])

    votes = person.votes.all().select_related(
        "vote_event", "vote_event__bill")[:RECENT_VOTES_TO_SHOW]
    person.vote_events = []
    for vote in votes:
        vote_event = vote.vote_event
        vote_event.legislator_vote = vote
        person.vote_events.append(vote_event)

    return render(
        request,
        "public/views/legislator.html",
        {
            "state": state,
            "person": person,
            "state_nav": "legislators",
            "retired": retired,
            "district_maybe": district_maybe,
        },
    )
Exemple #4
0
def convert_bill(b, include_votes):
    try:
        abstract = b.abstracts.all()[0].abstract
    except IndexError:
        abstract = ""

    chamber = b.from_organization.classification
    state = jid_to_abbr(b.legislative_session.jurisdiction_id)

    try:
        openstates_id = b.legacy_mapping.all()[0].legacy_id
    except IndexError:
        openstates_id = ""

    if include_votes:
        votes = [
            convert_vote(v, chamber, state, openstates_id)
            for v in b.votes.all()
        ]
    else:
        votes = None

    return {
        "title": b.title,
        "summary": abstract,
        "created_at": b.created_at.strftime(DATE_FORMAT),
        "updated_at": b.updated_at.strftime(DATE_FORMAT),
        "id": openstates_id,
        "all_ids": [openstates_id],
        "chamber": chamber,
        "state": state,
        "session": b.legislative_session.identifier,
        "type": b.classification,
        "bill_id": b.identifier,
        "actions": [convert_action(a) for a in b.actions.all()],
        "sources": [{
            "url": s.url
        } for s in b.sources.all()],
        "sponsors": [convert_sponsor(sp) for sp in b.sponsorships.all()],
        "versions": convert_versions(b.versions.all()),
        "documents": convert_versions(b.documents.all()),
        "alternate_titles": [alt.title for alt in b.other_titles.all()],
        "votes": votes,
        "action_dates": {
            "first": expand_date(b.first_action),
            "last": expand_date(b.last_action),
            # TODO - needed?
            "passed_upper": None,
            "passed_lower": None,
            "signed": None,
        },
        "scraped_subjects": b.subject,
        "alternate_bill_ids": [],
        "subjects": [],
        "companions": [],
    }
Exemple #5
0
def convert_post(post):
    abbr = jid_to_abbr(post.organization.jurisdiction_id)
    return {
        "division_id": post.division_id,
        "boundary_id": post.division_id,
        "name": post.label,
        "chamber": post.organization.classification,
        "abbr": abbr,
        "legislators": [],  # TODO?
        "num_seats": 1,
        "id": f"{abbr}-{post.organization.classification}-{post.label}",
    }
Exemple #6
0
def convert_post(post):
    abbr = jid_to_abbr(post.organization.jurisdiction_id)
    return {
        'division_id': post.division_id,
        'boundary_id': post.division_id,
        'name': post.label,
        'chamber': post.organization.classification,
        'abbr': abbr,
        'legislators': [],   # TODO?
        'num_seats': 1,
        'id': f'{abbr}-{post.organization.classification}-{post.label}',
    }
Exemple #7
0
def convert_bill(b, include_votes):
    try:
        abstract = b.abstracts.all()[0].abstract
    except IndexError:
        abstract = ""

    chamber = b.from_organization.classification
    state = jid_to_abbr(b.legislative_session.jurisdiction_id)

    try:
        openstates_id = b.legacy_mapping.all()[0].legacy_id
    except IndexError:
        openstates_id = ''

    if include_votes:
        votes = [convert_vote(v, chamber, state, openstates_id) for v in b.votes.all()]
    else:
        votes = None

    return {
        'title': b.title,
        'summary': abstract,
        'created_at': b.created_at.strftime(DATE_FORMAT),
        'updated_at': b.updated_at.strftime(DATE_FORMAT),
        'id': openstates_id,
        'all_ids': [openstates_id],
        'chamber': chamber,
        'state': state,
        'session': b.legislative_session.identifier,
        'type': b.classification,
        'bill_id': b.identifier,
        'actions': [convert_action(a) for a in b.actions.all()],
        'sources': [{'url': s.url} for s in b.sources.all()],
        'sponsors': [convert_sponsor(sp) for sp in b.sponsorships.all()],
        'versions': convert_versions(b.versions.all()),
        'documents': convert_versions(b.documents.all()),
        'alternate_titles': [alt.title for alt in b.other_titles.all()],
        'votes': votes,
        'action_dates': {
            'first': expand_date(b.first_action),
            'last': expand_date(b.last_action),
            # TODO - needed?
            'passed_upper': None,
            'passed_lower': None,
            'signed': None,
        },
        'scraped_subjects': b.subject,
        'alternate_bill_ids': [],
        'subjects': [],
        'companions': [],
    }
Exemple #8
0
def delta_set_to_pr(delta_set: DeltaSet):
    """
    get a list of person IDs mapped to lists of DiffItem and generate a github PR
    """
    person_deltas = {}
    states = set()
    for pd in delta_set.person_deltas.all():
        person_deltas[pd.person_id] = pd.data_changes
        states.add(jid_to_abbr(pd.person.current_jurisdiction_id))

    files_by_id = get_files(person_deltas.keys(), states=states)

    new_files = {}
    for person_id in person_deltas:
        file = files_by_id[person_id]
        new_files[file.path] = patch_file(file, person_deltas[person_id])

    url = create_pr(f"people_admin_deltas/{delta_set.id}", delta_set.name,
                    new_files)
    return url
Exemple #9
0
def vote(request, vote_id):
    vote = get_object_or_404(
        VoteEvent.objects.all().select_related(
            "organization",
            "legislative_session",
            "bill",
            "bill__legislative_session",
            "bill__from_organization",
            "bill__legislative_session__jurisdiction",
        ),
        pk="ocd-vote/" + vote_id,
    )
    state = jid_to_abbr(vote.organization.jurisdiction_id)
    vote_counts = sorted(vote.counts.all(), key=_vote_sort_key)
    person_votes = sorted(vote.votes.all().select_related("voter"),
                          key=_vote_sort_key)

    # add percentages to vote_counts
    total = sum(vc.value for vc in vote_counts)
    if total:
        for vc in vote_counts:
            vc.percent = vc.value / total * 100

    # aggregate voter ids into one query
    voter_ids_to_query = [pv.voter_id for pv in person_votes if pv.voter_id]
    voter_parties = defaultdict(list)
    # party -> option -> value
    party_votes = defaultdict(lambda: defaultdict(int))
    for membership in Membership.objects.filter(
            person_id__in=voter_ids_to_query,
            organization__classification="party").select_related(
                "organization"):
        voter_parties[membership.person_id].append(
            membership.organization.name)

    # attach party to people & calculate party-option crosstab
    for pv in person_votes:
        # combine other options
        if pv.option not in ("yes", "no"):
            option = "other"
        else:
            option = pv.option

        if pv.voter_id:
            pv.party = voter_parties[pv.voter_id][0]
            party_votes[pv.party][option] += 1
        else:
            party_votes["Unknown"][option] += 1

    # only show party breakdown if most people are matched
    if not person_votes or (len(voter_parties) / len(person_votes) < 0.8):
        party_votes = None
    else:
        party_votes = sorted(dict(party_votes).items())

    return render(
        request,
        "public/views/vote.html",
        {
            "state": state,
            "state_nav": "bills",
            "vote": vote,
            "vote_counts": vote_counts,
            "person_votes": person_votes,
            "party_votes": party_votes,
        },
    )
Exemple #10
0
def all_metadata(request):
    return JsonResponse([v1_metadata(jid_to_abbr(j.id), j) for j in jurisdictions_qs()],
                        safe=False)
Exemple #11
0
def test_jid_to_abbr():
    assert jid_to_abbr(
        "ocd-jurisdiction/country:us/state:nc/government") == "nc"
Exemple #12
0
def convert_legislator(leg):
    if leg.given_name and leg.family_name:
        first_name = leg.given_name
        last_name = leg.family_name
        suffixes = ""
    else:
        last_name = leg.name
        suffixes = first_name = ""

    legacy_ids = [
        oid.identifier for oid in leg.identifiers.all()
        if oid.scheme == "legacy_openstates"
    ]

    if not legacy_ids:
        legacy_ids = ["~not available~"]

    party = leg.primary_party
    state = jid_to_abbr(leg.current_jurisdiction_id)
    chamber = None
    district = None

    if leg.current_role:
        chamber = leg.current_role["org_classification"]
        district = leg.current_role["district"]

    email = None
    offices = defaultdict(dict)
    for cd in leg.contact_details.all():
        offices[cd.note][cd.type] = cd.value
        if cd.type == "email" and not email:
            email = cd.value

    active = bool(chamber and district)

    try:
        url = leg.links.all()[0].url
    except IndexError:
        url = ""

    return {
        "id":
        legacy_ids[0],
        "leg_id":
        legacy_ids[0],
        "all_ids":
        legacy_ids,
        "full_name":
        leg.name,
        "first_name":
        first_name,
        "last_name":
        last_name,
        "suffix":
        suffixes,
        "photo_url":
        leg.image,
        "url":
        url,
        "email":
        email,
        "party":
        party,
        "chamber":
        chamber,
        "district":
        district,
        "state":
        state,
        "sources": [{
            "url": s.url
        } for s in leg.sources.all()],
        "active":
        active,
        "roles": [{
            "term": static.TERMS[state][-1]["name"],
            "district": district,
            "chamber": chamber,
            "state": state,
            "party": party,
            "type": "member",
            "start_date": None,
            "end_date": None,
        }] if active else [],
        "offices": [{
            "name":
            label,
            "fax":
            details.get("fax"),
            "phone":
            details.get("voice"),
            "email":
            details.get("email"),
            "address":
            details.get("address"),
            "type":
            "capitol" if "capitol" in label.lower() else "district",
        } for label, details in offices.items()],
        "old_roles": {},
        "middle_name":
        "",
        "country":
        "us",
        "level":
        "state",
        "created_at":
        leg.created_at.strftime(DATE_FORMAT),
        "updated_at":
        leg.updated_at.strftime(DATE_FORMAT),
    }
def person(request, person_id):
    SPONSORED_BILLS_TO_SHOW = 4
    RECENT_VOTES_TO_SHOW = 3

    try:
        ocd_person_id = decode_uuid(person_id)
    except ValueError:
        ocd_person_id = (
            person_id  # will be invalid and raise 404, but useful in logging later
        )
    person = get_object_or_404(
        Person.objects.prefetch_related("memberships__organization"),
        pk=ocd_person_id,
    )

    # to display district in front of district name, or not?
    district_maybe = ""

    # canonicalize the URL
    canonical_url = pretty_url(person)
    if request.path != canonical_url:
        return redirect(canonical_url, permanent=True)

    if not person.current_jurisdiction_id:
        state = None
        retired = True
    elif not person.current_role:
        #  this breaks if they held office in two states, but we don't really worry about that
        state = jid_to_abbr(person.current_jurisdiction_id)
        retired = True
    else:
        state = jid_to_abbr(person.current_jurisdiction_id)
        retired = False
        # does it start with a number?
        if str(person.current_role["district"])[0] in "0123456789":
            district_maybe = "District"
    person.all_links = list(person.links.all())
    person.all_offices = list(person.offices.all())

    person.sponsored_bills = list(Bill.objects.all().select_related(
        "legislative_session",
        "legislative_session__jurisdiction",
    ).filter(sponsorships__person=person).order_by(
        "-created_at", "id")[:SPONSORED_BILLS_TO_SHOW])

    votes = (person.votes.all().select_related(
        "vote_event", "vote_event__bill").order_by("-vote_event__start__date")
             [:RECENT_VOTES_TO_SHOW])
    person.vote_events = []
    for vote in votes:
        vote_event = vote.vote_event
        vote_event.legislator_vote = vote
        person.vote_events.append(vote_event)

    return render(
        request,
        "public/views/legislator.html",
        {
            "state": state,
            "person": person,
            "state_nav": "legislators",
            "retired": retired,
            "district_maybe": district_maybe,
        },
    )