def elections(office, cycle, state=None, district=None): # Get all cycles up until the cycle from the URL if it's beyond the current cycle # this fixes the issue of an election page not showing user-provided cycle # in the cycle select max_cycle = cycle if cycle > utils.current_cycle( ) else utils.current_cycle() cycles = utils.get_cycles(max_cycle) if office.lower() == 'president': cycles = [each for each in cycles if each % 4 == 0] elif office.lower() == 'senate': cycles = utils.get_state_senate_cycles(state) if office.lower() not in ['president', 'senate', 'house']: abort(404) if state and state.upper() not in constants.states: abort(404) return render_template( 'elections.html', office=office, office_code=office[0], parent='data', cycle=cycle, cycles=cycles, state=state, state_full=constants.states[state.upper()] if state else None, district=district, title=utils.election_title(cycle, office, state, district), )
def elections(office, cycle, state=None, district=None): # Get all cycles up until the cycle from the URL if it's beyond the current cycle # this fixes the issue of an election page not showing user-provided cycle # in the cycle select max_cycle = cycle if cycle > utils.current_cycle() else utils.current_cycle() cycles = utils.get_cycles(max_cycle) if office.lower() == 'president': cycles = [each for each in cycles if each % 4 == 0] elif office.lower() == 'senate': cycles = utils.get_state_senate_cycles(state) if office.lower() not in ['president', 'senate', 'house']: abort(404) if state and state.upper() not in constants.states: abort(404) return render_template( 'elections.html', office=office, office_code=office[0], parent='data', cycle=cycle, cycles=cycles, state=state, state_full=constants.states[state.upper()] if state else None, district=district, title=utils.election_title(cycle, office, state, district), )
def load_with_nested(primary_type, primary_id, secondary_type, cycle=None): path = ('history', str(cycle)) if cycle else () # Hack: If no history records are found, get the latest detail record # TODO(jmcarp) Roll back once #875 is resolved try: data = load_single_type(primary_type, primary_id, *path) except NotFound: data = load_single_type(primary_type, primary_id) cycle = cycle or min(utils.current_cycle(), max(data['cycles'])) path = ('history', str(cycle)) nested_data = load_nested_type(primary_type, primary_id, secondary_type, *path) return data, nested_data['results'], cycle
def _get_default_cycles(): cycle = utils.current_cycle() return list(range(cycle - 4, cycle + 2, 2))
def get_cycles(): return range(utils.current_cycle(), START_YEAR, -2)
def restrict_cycles(value, start_year=START_YEAR): return [each for each in value if start_year <= each <= utils.current_cycle()]
def render_candidate(candidate, committees, cycle, election_full=True): # candidate fields will be top-level in the template tmpl_vars = candidate tmpl_vars['parent'] = 'data' tmpl_vars['cycle'] = cycle tmpl_vars['election_year'] = next( (year for year in sorted(candidate['election_years']) if year >= cycle), None, ) tmpl_vars['result_type'] = 'candidates' tmpl_vars['duration'] = election_durations.get(candidate['office'], 2) tmpl_vars['min_cycle'] = cycle - tmpl_vars['duration'] if election_full else cycle tmpl_vars['election_full'] = election_full tmpl_vars['report_type'] = report_types.get(candidate['office']) tmpl_vars['context_vars'] = { 'cycles': candidate['cycles'], 'name': candidate['name'], 'cycle': cycle, 'electionFull': election_full, 'candidateID': candidate['candidate_id'] } # In the case of when a presidential or senate candidate has filed # for a future year that's beyond the current cycle, # set a max_cycle var to the current cycle we're in # and when calling the API for totals, set election_full to False. # The max_cycle value is also referenced in the templates for setting # the cycle for itemized tables. Because these are only in 2-year chunks, # the cycle should never be beyond the one we're in. tmpl_vars['cycles'] = [cycle for cycle in candidate['cycles'] if cycle <= utils.current_cycle()] tmpl_vars['max_cycle'] = cycle if cycle <= utils.current_cycle() else utils.current_cycle() tmpl_vars['show_full_election'] = election_full if cycle <= utils.current_cycle() else False # Annotate committees with most recent available cycle tmpl_vars['aggregate_cycles'] = ( list(range(cycle, cycle - tmpl_vars['duration'], -2)) if election_full else [cycle] ) for committee in committees: committee['related_cycle'] = ( max(cycle for cycle in tmpl_vars['aggregate_cycles'] if cycle in committee['cycles']) if election_full else candidate['two_year_period'] ) # Group the committees by designation committee_groups = groupby(committees, lambda each: each['designation']) committees_authorized = committee_groups.get('P', []) + committee_groups.get('A', []) tmpl_vars['committee_groups'] = committee_groups tmpl_vars['committees_authorized'] = committees_authorized tmpl_vars['committee_ids'] = [committee['committee_id'] for committee in committees_authorized] # Get aggregate totals for the financial summary # And pass through the data processing utils aggregate = api_caller.load_candidate_totals( candidate['candidate_id'], cycle=tmpl_vars['max_cycle'], election_full=tmpl_vars['show_full_election'], ) if aggregate: tmpl_vars['raising_summary'] = utils.process_raising_data(aggregate) tmpl_vars['spending_summary'] = utils.process_spending_data(aggregate) tmpl_vars['cash_summary'] = utils.process_cash_data(aggregate) tmpl_vars['aggregate'] = aggregate # Get totals for the last two-year period of a cycle for showing on # raising and spending tabs two_year_totals = api_caller.load_candidate_totals( candidate['candidate_id'], cycle=tmpl_vars['max_cycle'], election_full=False ) if two_year_totals: tmpl_vars['two_year_totals'] = two_year_totals # Get the statements of candidacy statement_of_candidacy = api_caller.load_candidate_statement_of_candidacy( candidate['candidate_id'], cycle=cycle ) if statement_of_candidacy: for statement in statement_of_candidacy: # convert string to python datetime and parse for readable output statement['receipt_date'] = datetime.datetime.strptime(statement['receipt_date'], '%Y-%m-%dT%H:%M:%S') statement['receipt_date'] = statement['receipt_date'].strftime('%m/%d/%Y') tmpl_vars['statement_of_candidacy'] = statement_of_candidacy # Get all the elections tmpl_vars['elections'] = sorted( zip(candidate['election_years'], candidate['election_districts']), key=lambda pair: pair[0], reverse=True, ) return render_template('candidates-single.html', **tmpl_vars)
def render_committee(committee, candidates, cycle, redirect_to_previous): # committee fields will be top-level in the template tmpl_vars = committee tmpl_vars['parent'] = 'data' tmpl_vars['cycle'] = cycle tmpl_vars['year'] = to_date(committee, cycle) tmpl_vars['result_type'] = 'committees' # Link to current cycle if candidate has a corresponding page, else link # without cycle query parameter # See https://github.com/18F/openFEC/issues/1536 for candidate in candidates: election_years = [ election_year for election_year in candidate['election_years'] if election_year - election_durations[candidate['office']] < cycle <= election_year ] candidate['related_cycle'] = max(election_years) if election_years else None # add related candidates a level below tmpl_vars['candidates'] = candidates financials = api_caller.load_cmte_financials(committee['committee_id'], cycle=cycle) tmpl_vars['report_type'] = report_types.get(committee['committee_type'], 'pac-party') tmpl_vars['reports'] = financials['reports'] tmpl_vars['totals'] = financials['totals'] tmpl_vars['context_vars'] = { 'cycle': cycle, 'timePeriod': str(cycle - 1) + '–' + str(cycle), 'name': committee['name'], } if financials['reports'] and financials['totals']: # Format the current two-year-period's totals using the process utilities if committee['committee_type'] == 'I': # IE-only committees have very little data, so they just get this one tmpl_vars['ie_summary'] = utils.process_ie_data(financials['totals'][0]) else: # All other committees have three tables tmpl_vars['raising_summary'] = utils.process_raising_data(financials['totals'][0]) tmpl_vars['spending_summary'] = utils.process_spending_data(financials['totals'][0]) tmpl_vars['cash_summary'] = utils.process_cash_data(financials['totals'][0]) if redirect_to_previous and not financials['reports']: # If there's no reports, find the first year with reports and redirect there for c in sorted(committee['cycles'], reverse=True): financials = api_caller.load_cmte_financials(committee['committee_id'], cycle=c) if financials['reports']: return redirect( url_for('committee_page', c_id=committee['committee_id'], cycle=c) ) # If it's not a senate committee and we're in the current cycle # check if there's any raw filings in the last two days if committee['committee_type'] != 'S' and cycle == utils.current_cycle(): raw_filings = api_caller._call_api( 'efile', 'filings', cycle=cycle, committee_id=committee['committee_id'], min_receipt_date=utils.two_days_ago() ) if len(raw_filings.get('results')) > 0: tmpl_vars['has_raw_filings'] = True else: tmpl_vars['has_raw_filings'] = False return render_template('committees-single.html', **tmpl_vars)