Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process Form 497 Page 2 (Late Expenditures) #31

Merged
merged 5 commits into from
Sep 21, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/referendum/4/supporting/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"id": 2,
"name": "Causa Justa :: Just Cause (nonprofit 501(c)(3))",
"payee": "Causa Justa :: Just Cause (nonprofit 501(c)(3))",
"amount": 33930.57
"amount": 94470.86
}
],
"total_contributions": 456,
Expand Down
16 changes: 15 additions & 1 deletion calculators/candidate_expenditures_by_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,21 @@ def expenditures_by_candidate_by_type
ORDER BY "Expn_Code", "Filer_ID", "Report_Num" DESC
SQL

results.each do |result|
# 497 does not contain "Expn_Code" making this calculator pretty useless
# for those contributions.
# To make the numbers line up closer, we'll bucket those all under "Not
# Stated".
late_expenditures = ActiveRecord::Base.connection.execute(<<-SQL)
SELECT DISTINCT ON ("Filer_ID")
"Filer_ID", '' AS "Expn_Code", SUM("Amount") AS "Total"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should '' be 'Not stated'? Or maybe null so it's easier to handle on the frontend?

FROM "efile_COAK_2016_497"
WHERE "Filer_ID" IN ('#{@candidates_by_filer_id.keys.join "','"}')
AND "Form_Type" = 'F497P2'
GROUP BY "Filer_ID", "Report_Num"
ORDER BY "Filer_ID", "Report_Num" DESC
SQL

(results.to_a + late_expenditures.to_a).each do |result|
hash[result['Filer_ID']] ||= {}
hash[result['Filer_ID']][result['Expn_Code']] = result['Total']
end
Expand Down
66 changes: 66 additions & 0 deletions calculators/referendum_supporters_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ def fetch
ORDER BY "Filer_ID", "Filer_NamL", "Bal_Name", "Sup_Opp_Cd", "Report_Num" DESC
SQL

late_expenditures = ActiveRecord::Base.connection.execute(<<-SQL)
SELECT DISTINCT ON ("Filer_ID", "Filer_NamL", "Bal_Name")
"Filer_ID", "Filer_NamL", "Bal_Name", SUM("Amount") AS "Total_Amount"
FROM "efile_COAK_2016_497"
WHERE "Bal_Name" IS NOT NULL
AND "Form_Type" = 'F497P2'
GROUP BY "Filer_ID", "Filer_NamL", "Bal_Name", "Report_Num"
ORDER BY "Filer_ID", "Filer_NamL", "Bal_Name", "Report_Num" DESC
SQL

supporting_by_measure_name = {}
opposing_by_measure_name = {}

Expand All @@ -29,6 +39,37 @@ def fetch
end
end

late_expenditures.each do |row|
sup_opp_cd = guess_whether_committee_supports_measure(row['Filer_ID'], row['Bal_Name'])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this ever come up empty? In that case, we just don't count the money?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like if we can't guess then we drop it. Its not likely to happen too often.
On a related note, I think I saw the same ballot measure referred by two different names.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we drop it. I created #35 as a issue to track our tracking of how many records / how much money we skip because we can't find a match. We can keep adding more to that issue as we introduce more fuzzy matching into our processing.

if sup_opp_cd == 'S'
supporting_by_measure_name[row['Bal_Name']] ||= []
existing_idx = supporting_by_measure_name[row['Bal_Name']].find_index do |existing_row|
existing_row['Filer_ID'].to_s == row['Filer_ID'].to_s
end

if existing_idx
supporting_by_measure_name[row['Bal_Name']][existing_idx]['Total_Amount'] +=
row['Total_Amount']
else
supporting_by_measure_name[row['Bal_Name']] << row
end
elsif sup_opp_cd == 'O'
opposing_by_measure_name[row['Bal_Name']] ||= []
opposing_by_measure_name[row['Bal_Name']] << row
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right, aren't you appending the row twice?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good catch.


existing_idx = opposing_by_measure_name[row['Bal_Name']].find_index do |existing_row|
existing_row['Filer_ID'].to_s == row['Filer_ID'].to_s
end

if existing_idx
opposing_by_measure_name[row['Bal_Name']][existing_idx]['Total_Amount'] +=
row['Total_Amount']
else
opposing_by_measure_name[row['Bal_Name']] << row
end
end
end

[
# { bal_name => rows } , calculation name
[supporting_by_measure_name, :supporting_organizations],
Expand Down Expand Up @@ -77,4 +118,29 @@ def committee_from_expenditure(expenditure)

committee
end

# Form 497 Page 2 (Late Expenditures) includes the ballot measure name and
# committee ID, but does not indicate whether that expenditure was in support
# or opposition of the ballot measure.
#
# This is not perfect, but it should get us pretty close.
def guess_whether_committee_supports_measure(committee_id, bal_name)
@_guess_cache ||=
begin
guesses = ActiveRecord::Base.connection.execute(<<-SQL)
SELECT "Filer_ID", "Bal_Name", "Sup_Opp_Cd"
Copy link
Collaborator

@mikeubell mikeubell Sep 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use SELECT DISTINCT rather than GROUP BY, its probably its processed about the same but I think it is clearer that is what you are doing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I didn't use the Report_Num here because it seemed unlikely to me that the Sup_Opp_Cd would change between amendments.

FROM "efile_COAK_2016_E-Expenditure"
WHERE "Bal_Name" IS NOT NULL
GROUP BY "Filer_ID", "Bal_Name", "Sup_Opp_Cd"
SQL

guesses.index_by do |row|
row.values_at('Filer_ID', 'Bal_Name').map(&:to_s)
end
end

if row = @_guess_cache[[committee_id.to_s, bal_name]]
row['Sup_Opp_Cd']
end
end
end