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

Allow multiple jurisdictions #76

Merged
merged 2 commits into from
Oct 14, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@
/yarn-error.log
yarn-debug.log*
.yarn-integrity
.idea
2 changes: 1 addition & 1 deletion app/controllers/alert_subscribers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ def set_alert_subscriber
end

def alert_subscriber_params
params.fetch(:alert_subscriber).permit(:email)
params.fetch(:alert_subscriber).permit(:email).merge(netfile_agency: NetfileAgency.coak)
end
end
15 changes: 8 additions & 7 deletions app/lib/disclosure_downloader.rb
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
# frozen_string_literal: true

class DisclosureDownloader
def initialize
def initialize(agency = NetfileAgency.coak)
@netfile = Netfile::Client.new
@agency = agency
end

def download
latest = Filing.order(filed_at: :desc).first
latest = Filing.where(netfile_agency: @agency).order(filed_at: :desc).first
puts '==================================================================='
puts 'Beginning State:'
puts "Beginning State for Netfile agency #{@agency.shortcut}:"
puts
puts "Filings: #{Filing.count}"
puts "Filings: #{Filing.where(netfile_agency: @agency).count}"
puts "Latest: #{latest&.filed_at}"
puts '==================================================================='

@netfile.each_filing do |json|
@netfile.each_filing(agency: @agency) do |json|
filing = Filing.from_json(json)

if filing.new_record?
Expand Down Expand Up @@ -46,11 +47,11 @@ def download
end
end

latest = Filing.order(filed_at: :desc).first
latest = Filing.where(netfile_agency: @agency).order(filed_at: :desc).first
puts '==================================================================='
puts 'Ending State:'
puts
puts "Filings: #{Filing.count}"
puts "Filings: #{Filing.where(netfile_agency: @agency).count}"
puts "Latest: #{latest&.filed_at}"
puts '==================================================================='
end
Expand Down
29 changes: 17 additions & 12 deletions app/lib/disclosure_emailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,29 @@ def initialize(date)
end

def send_email
puts '==================================================================='
puts 'Emailing:'
puts
puts "Filings in date range: #{filings_in_date_range.length}"
puts '==================================================================='
return if filings_in_date_range.none?
NetfileAgency.each_supported_agency do |agency|
subscribers = AlertSubscriber.subscribed.where(netfile_agency: agency)
filings = filings_in_date_range(agency)

AlertSubscriber.subscribed.find_each do |subscriber|
AlertMailer
.daily_alert(subscriber, @date, filings_in_date_range, notices_in_date_range)
.deliver_now
puts '==================================================================='
puts "Emailing to #{subscribers.count} subscribers of #{agency.shortcut}:"
puts
puts "Total filings in date range: #{filings.length}"
puts '==================================================================='
return if filings.none?

AlertSubscriber.subscribed.find_each do |subscriber|
AlertMailer
.daily_alert(subscriber, @date, filings, notices_in_date_range)
.deliver_now
end
end
end

private

def filings_in_date_range
Filing.filed_on_date(@date)
def filings_in_date_range(agency)
Filing.filed_on_date(@date).where(netfile_agency: agency)
end

def notices_in_date_range
Expand Down
6 changes: 3 additions & 3 deletions app/lib/netfile/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,15 @@ def get_filing(filing_id)
end
end

def each_filing(form: nil, &block)
return to_enum(:each_filing) unless block_given?
def each_filing(form: nil, agency:, &block)
return to_enum(:each_filing, form: form, agency: agency) unless block_given?

Net::HTTP.start(BASE_URL.host, BASE_URL.port, use_ssl: true) do |http|
with_pagination do |current_page|
request = Net::HTTP::Post.new(BASE_URL + 'public/list/filing')
request['Accept'] = 'application/json'
request.body = URI.encode_www_form(
AID: 'COAK',
AID: agency.shortcut,
CurrentPageIndex: current_page,
Form: form,
)
Expand Down
4 changes: 2 additions & 2 deletions app/mailers/alert_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ class AlertMailer < ApplicationMailer
track open: true, click: true, utm_params: true,
user: -> { AlertSubscriber.subscribed.find_by(email: message.to.first) }

def daily_alert(alert_subscriber, date_or_date_range, filings_in_date_range, notice)
def daily_alert(alert_subscriber, date_or_date_range, filings, notice)
@alert_subscriber = alert_subscriber
@forms = Forms.from_filings(filings_in_date_range)
@forms = Forms.from_filings(filings)
@email_notice = notice

subject_date = if date_or_date_range.is_a?(Range)
Expand Down
1 change: 1 addition & 0 deletions app/models/alert_subscriber.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class AlertSubscriber < ApplicationRecord
scope :unsubscribed, -> { where.not(unsubscribed_at: nil) }

has_many :ahoy_messages, foreign_key: :user_id
belongs_to :netfile_agency

validates :email, format: /\A[^@]+@[^\.]+\.[\w]+\z/i

Expand Down
2 changes: 2 additions & 0 deletions app/models/filing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Filing < ApplicationRecord
has_many :election_candidates, foreign_key: :fppc_id, primary_key: :filer_id
has_one :election_committee, foreign_key: :fppc_id, primary_key: :filer_id
has_one :amended_filing, class_name: 'Filing', primary_key: :amended_filing_id, foreign_key: :id
belongs_to :netfile_agency

def election_referendum
ElectionReferendum
Expand All @@ -28,6 +29,7 @@ def self.from_json(json)
record.filer_id = json['filerStateId']
record.filer_name = json['filerName']
record.title = json['title']
record.netfile_agency = NetfileAgency.by_netfile_id(json['agency'])
record.filed_at = DateTime.parse(json['filingDate'])
record.amendment_sequence_number = json['amendmentSequenceNumber']
record.amended_filing_id = json['amendedFilingId']
Expand Down
24 changes: 24 additions & 0 deletions app/models/netfile_agency.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class NetfileAgency < ApplicationRecord
def self.create_supported_agencies
find_or_create_by(netfile_id: 13, shortcut: 'COAK', name: 'Oakland, City of')
find_or_create_by(netfile_id: 52, shortcut: 'SFO', name: 'San Francisco Ethics Commission')
end

def self.coak
@_coak ||= find_by(shortcut: 'COAK')
end

def self.sfo
@_sfo ||= find_by(shortcut: 'SFO')
end

def self.each_supported_agency(&block)
block.call(coak)
block.call(sfo)
end

def self.by_netfile_id(id)
@_by_id ||= all.index_by(&:netfile_id)
@_by_id.fetch(id)
end
end
29 changes: 29 additions & 0 deletions db/migrate/20221014195907_add_agency_id_to_filings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class AddAgencyIdToFilings < ActiveRecord::Migration[7.0]
def up
create_table :netfile_agencies do |t|
t.integer :netfile_id
t.string :shortcut
t.string :name

t.index :netfile_id, unique: true
t.index :shortcut, unique: true
end

oakland = NetfileAgency.create(netfile_id: 13, shortcut: 'COAK', name: 'Oakland, City of')
_sf = NetfileAgency.create(netfile_id: 52, shortcut: 'SFO', name: 'San Francisco Ethics Commission')

change_table :filings do |t|
t.references :netfile_agency, default: oakland.id
end

change_table :alert_subscribers do |t|
t.references :netfile_agency, default: oakland.id
end
end

def down
remove_reference :netfile_filings, :agency
remove_reference :netfile_alert_subscribers, :agency
drop_table :netfile_agencies
end
end
14 changes: 13 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_10_09_211246) do
ActiveRecord::Schema[7.0].define(version: 2022_10_14_195907) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -60,6 +60,8 @@
t.string "token"
t.datetime "unsubscribed_at", precision: nil
t.datetime "confirmed_at", precision: nil
t.bigint "netfile_agency_id", default: 1
t.index ["netfile_agency_id"], name: "index_alert_subscribers_on_netfile_agency_id"
t.index ["token"], name: "index_alert_subscribers_on_token"
end

Expand Down Expand Up @@ -111,6 +113,16 @@
t.datetime "filed_at", precision: nil
t.json "contents"
t.xml "contents_xml"
t.bigint "netfile_agency_id", default: 1
t.index ["netfile_agency_id"], name: "index_filings_on_netfile_agency_id"
end

create_table "netfile_agencies", force: :cascade do |t|
t.integer "netfile_id"
t.string "shortcut"
t.string "name"
t.index ["netfile_id"], name: "index_netfile_agencies_on_netfile_id", unique: true
t.index ["shortcut"], name: "index_netfile_agencies_on_shortcut", unique: true
end

create_table "notices", force: :cascade do |t|
Expand Down
8 changes: 6 additions & 2 deletions lib/tasks/disclosure_alert.rake
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ namespace :disclosure_alert do

desc 'Download latest records'
task download: :environment do
DisclosureDownloader.new.download
NetfileAgency.each_supported_agency do |agency|
DisclosureDownloader.new(agency).download
end
end

desc 'Download latest records and send email'
task download_and_email_daily: :with_configuration do
today = TZInfo::Timezone.get('America/Los_Angeles').now.to_date
DisclosureDownloader.new.download
NetfileAgency.each_supported_agency do |agency|
DisclosureDownloader.new(agency).download
end
DisclosureEmailer.new(today - 1).send_email
end

Expand Down
3 changes: 2 additions & 1 deletion spec/admin/alert_subscribers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
let!(:alert_subscriber) do
AlertSubscriber.create!(
email: '[email protected]',
confirmed_at: Time.now
confirmed_at: Time.now,
netfile_agency: NetfileAgency.coak
)
end

Expand Down
7 changes: 4 additions & 3 deletions spec/controllers/alert_subscribers_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
expect(subscriber.token).to be_present
expect(subscriber.confirmed_at).to be_nil
expect(subscriber.unsubscribed_at).to be_nil
expect(subscriber.netfile_agency).to eq(NetfileAgency.coak)
end

it 'sends a AlertSubscriberMailer.confirm email' do
Expand All @@ -53,7 +54,7 @@
end

describe '#edit' do
let(:alert_subscriber) { AlertSubscriber.create(email: '[email protected]') }
let(:alert_subscriber) { AlertSubscriber.create(email: '[email protected]', netfile_agency: NetfileAgency.coak) }
let(:request_token) { nil }

subject { get :edit, params: { id: alert_subscriber.id, token: request_token } }
Expand All @@ -72,7 +73,7 @@
end

describe '#destroy' do
let!(:alert_subscriber) { AlertSubscriber.create(email: '[email protected]') }
let!(:alert_subscriber) { AlertSubscriber.create(email: '[email protected]', netfile_agency: NetfileAgency.coak) }
let(:request_token) { nil }

subject { post :destroy, params: { id: alert_subscriber.id, token: request_token } }
Expand All @@ -99,7 +100,7 @@
describe '#confirm' do
render_views

let!(:alert_subscriber) { AlertSubscriber.create(email: '[email protected]') }
let!(:alert_subscriber) { AlertSubscriber.create(email: '[email protected]', netfile_agency: NetfileAgency.coak) }
let(:request_token) { nil }

subject { post :confirm, params: { id: alert_subscriber.id, token: request_token } }
Expand Down
3 changes: 2 additions & 1 deletion spec/controllers/webhooks_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
let(:subscriber) do
AlertSubscriber.create(
email: '[email protected]',
confirmed_at: Time.now
confirmed_at: Time.now,
netfile_agency: NetfileAgency.coak,
)
end
let!(:admin_user) { AdminUser.create(email: '[email protected]', password: 'secretpassword') }
Expand Down
4 changes: 2 additions & 2 deletions spec/helpers/alert_mailer_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
{ 'form_Type' => 'F460', 'line_Item' => '5', 'amount_A' => 1000 }, # total contributions received
]
end
let(:filing) { Filing.create(filer_id: 123, form: 30, contents: filing_contents) }
let(:filing) { Filing.create(filer_id: 123, form: 30, contents: filing_contents, netfile_agency: NetfileAgency.coak) }
let(:form) { Forms.from_filings([filing]).first }

it 'returns the value when there is no amended form' do
Expand All @@ -88,7 +88,7 @@

context 'with an amended form' do
let(:amended_filing_contents) { filing_contents.dup.tap { |c| c[0]['amount_A'] = 2000 } }
let(:filing_amendment) { Filing.create(form: 30, amended_filing_id: filing.id, contents: amended_filing_contents) }
let(:filing_amendment) { Filing.create(form: 30, amended_filing_id: filing.id, contents: amended_filing_contents, netfile_agency: NetfileAgency.coak) }
let(:form_amendment) { Forms.from_filings([filing_amendment]).first }

it 'returns an amended value' do
Expand Down
6 changes: 4 additions & 2 deletions spec/lib/disclosure_downloader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def initialize(fake_filings)
@filings = Array(fake_filings)
end

def each_filing(&block)
def each_filing(agency:, &block)
@filings.each { |filing| block.call(filing.metadata) }
end

Expand All @@ -31,7 +31,8 @@ def fetch_transaction_contents(id)
filingDate: "2022-10-12T17:50:07.0000000-07:00",
amendmentSequenceNumber: 0,
amendedFilingId: nil,
form: 36 # FPPC Form 496
form: 36, # FPPC Form 496
agency: NetfileAgency.coak.netfile_id,
}.stringify_keys
end
let(:fake_filing_data) do
Expand Down Expand Up @@ -70,6 +71,7 @@ def fetch_transaction_contents(id)

last_filing = Filing.last
expect(last_filing.title).to eq(fake_filing.metadata['title'])
expect(last_filing.netfile_agency).to eq(NetfileAgency.coak)
end
end
end
Loading