Skip to content

Commit 88bab9c

Browse files
committed
Fetch invoices and payments from freshbooks , store them in the db.
- Upgraded Rspec to use the 3.X structured config files - switch to capybara webkit
1 parent 1f2b295 commit 88bab9c

32 files changed

+636
-89
lines changed

.rspec

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
--color --format Fuubar
1+
--color
2+
--require spec_helper

.rubocop.yml

+2-6
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,23 @@ AllCops:
77
- 'Guardfile'
88
- 'vendor/bundle/**/*'
99

10-
# Offense count: 94
11-
# Cop supports --auto-correct.
1210
# Configuration parameters: EnforcedStyle, SupportedStyles.
1311
Style/StringLiterals:
1412
Enabled: false
1513

16-
# Offense count: 57
14+
# Offense count: 45
1715
# Configuration parameters: AllowURI.
1816
Metrics/LineLength:
19-
Max: 120
17+
Max: 112
2018

2119
# We don't use this often but sometimes it improves readability
2220
# Configuration parameters: EnforcedStyle, SupportedStyles.
2321
Style/BracesAroundHashParameters:
2422
Enabled: false
2523

26-
# Offense count: 8
2724
Style/Documentation:
2825
Enabled: false
2926

3027
# Configuration parameters: EnforcedStyle, SupportedStyles.
3128
Style/IndentHash:
3229
Enabled: false
33-

Gemfile

+6-3
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ gem 'neat'
1717
gem 'nokogiri'
1818
gem 'paperclip'
1919
gem 'pg'
20-
gem 'pry'
2120
gem 'rails', '4.2.0'
2221
gem 'recipient_interceptor'
2322
gem 'redcarpet'
2423
gem 'sass-rails'
2524
gem 'therubyracer'
2625
gem 'uglifier'
2726
gem 'unicorn', require: false # Use unicorn as the app server
27+
gem 'ruby-freshbooks'
2828

2929
group :development do
3030
gem 'bitters'
@@ -36,15 +36,18 @@ end
3636
group :test do
3737
gem 'cucumber-rails', require: false
3838
gem 'database_cleaner'
39-
gem 'factory_girl_rails'
4039
gem 'fuubar'
4140
gem 'rake'
4241
gem 'rspec-rails'
43-
gem 'selenium-webdriver'
42+
gem 'capybara-webkit'
4443
gem 'shoulda-matchers', require: false
44+
gem 'webmock'
4545
end
4646

4747
group :development, :test do
48+
gem 'factory_girl_rails'
49+
gem 'pry'
50+
gem 'pry-byebug'
4851
gem 'rubocop', require: false
4952
end
5053

Gemfile.lock

+30-10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ GEM
3838
minitest (~> 5.1)
3939
thread_safe (~> 0.3, >= 0.3.4)
4040
tzinfo (~> 1.1)
41+
addressable (2.3.6)
4142
arel (6.0.0)
4243
ast (2.0.0)
4344
astrolabe (1.3.0)
@@ -56,21 +57,29 @@ GEM
5657
sass (~> 3.3)
5758
thor
5859
builder (3.2.2)
60+
byebug (3.5.1)
61+
columnize (~> 0.8)
62+
debugger-linecache (~> 1.2)
63+
slop (~> 3.6)
5964
capybara (2.4.4)
6065
mime-types (>= 1.16)
6166
nokogiri (>= 1.3.3)
6267
rack (>= 1.0.0)
6368
rack-test (>= 0.5.4)
6469
xpath (~> 2.0)
70+
capybara-webkit (1.4.1)
71+
capybara (>= 2.3.0, < 2.5.0)
72+
json
6573
celluloid (0.16.0)
6674
timers (~> 4.0.0)
67-
childprocess (0.5.5)
68-
ffi (~> 1.0, >= 1.0.11)
6975
climate_control (0.0.3)
7076
activesupport (>= 3.0)
7177
cocaine (0.5.5)
7278
climate_control (>= 0.0.3, < 1.0)
7379
coderay (1.1.0)
80+
columnize (0.9.0)
81+
crack (0.4.2)
82+
safe_yaml (~> 1.0.0)
7483
cucumber (1.3.17)
7584
builder (>= 2.1.2)
7685
diff-lcs (>= 1.1.3)
@@ -86,6 +95,7 @@ GEM
8695
curb (0.8.6)
8796
dalli (2.7.2)
8897
database_cleaner (1.3.0)
98+
debugger-linecache (1.2.0)
8999
delayed_job (4.0.6)
90100
activesupport (>= 3.0, < 5.0)
91101
delayed_job_active_record (4.0.3)
@@ -133,6 +143,9 @@ GEM
133143
rspec (>= 2.99.0, < 4.0)
134144
hike (1.2.3)
135145
hitimes (1.2.2)
146+
httparty (0.13.3)
147+
json (~> 1.8)
148+
multi_xml (>= 0.5.2)
136149
i18n (0.7.0)
137150
jquery-rails (3.1.2)
138151
railties (>= 3.0, < 5.0)
@@ -156,6 +169,7 @@ GEM
156169
minitest (5.5.0)
157170
multi_json (1.10.1)
158171
multi_test (0.1.1)
172+
multi_xml (0.5.5)
159173
neat (1.7.0)
160174
bourbon (>= 4.0)
161175
sass (>= 3.3)
@@ -175,6 +189,9 @@ GEM
175189
coderay (~> 1.1.0)
176190
method_source (~> 0.8.1)
177191
slop (~> 3.4)
192+
pry-byebug (2.0.0)
193+
byebug (~> 3.4)
194+
pry (~> 0.10)
178195
rack (1.6.0)
179196
rack-test (0.6.2)
180197
rack (>= 1.0)
@@ -243,8 +260,11 @@ GEM
243260
powerpack (~> 0.0.6)
244261
rainbow (>= 1.99.1, < 3.0)
245262
ruby-progressbar (~> 1.4)
263+
ruby-freshbooks (0.4.1)
264+
builder (>= 2.1.2)
265+
httparty (>= 0.5.0)
246266
ruby-progressbar (1.7.1)
247-
rubyzip (1.1.6)
267+
safe_yaml (1.0.4)
248268
sass (3.4.9)
249269
sass-rails (5.0.0)
250270
railties (>= 4.0.0, < 5.0)
@@ -253,11 +273,6 @@ GEM
253273
sprockets-rails (>= 2.0, < 4.0)
254274
tilt (~> 1.1)
255275
sax-machine (1.2.0)
256-
selenium-webdriver (2.44.0)
257-
childprocess (~> 0.5)
258-
multi_json (~> 1.0)
259-
rubyzip (~> 1.0)
260-
websocket (~> 1.0)
261276
shoulda-matchers (2.7.0)
262277
activesupport (>= 3.0.0)
263278
slop (3.6.0)
@@ -287,7 +302,9 @@ GEM
287302
kgio (~> 2.6)
288303
rack
289304
raindrops (~> 0.7)
290-
websocket (1.2.1)
305+
webmock (1.20.4)
306+
addressable (>= 2.3.6)
307+
crack (>= 0.3.2)
291308
xpath (2.0.0)
292309
nokogiri (~> 1.3)
293310

@@ -300,6 +317,7 @@ DEPENDENCIES
300317
bcrypt
301318
bitters
302319
bourbon
320+
capybara-webkit
303321
cucumber-rails
304322
dalli
305323
database_cleaner
@@ -320,16 +338,18 @@ DEPENDENCIES
320338
paperclip
321339
pg
322340
pry
341+
pry-byebug
323342
rails (= 4.2.0)
324343
rails_12factor
325344
rake
326345
recipient_interceptor
327346
redcarpet
328347
rspec-rails
329348
rubocop
349+
ruby-freshbooks
330350
sass-rails
331-
selenium-webdriver
332351
shoulda-matchers
333352
therubyracer
334353
uglifier
335354
unicorn
355+
webmock

app/models/freshbooks_invoice.rb

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class FreshbooksInvoice < ActiveRecord::Base
2+
validates :invoice_id, presence: true, uniqueness: true
3+
validates :number, presence: true
4+
validates :organization, presence: true
5+
validates :client_id, presence: true
6+
validates :status, presence: true
7+
validates :amount, presence: true
8+
validates :amount_outstanding, presence: true
9+
validates :paid, presence: true
10+
validates :date, presence: true
11+
validates :public_url, presence: true
12+
13+
FIELDS_TO_IMPORT = %w(
14+
invoice_id
15+
number
16+
organization
17+
client_id
18+
status
19+
amount
20+
paid
21+
date
22+
amount_outstanding
23+
)
24+
25+
def self.import(invoice)
26+
attributes = invoice.slice(*FIELDS_TO_IMPORT)
27+
attributes["public_url"] = invoice["links"]["client_view"]
28+
record = first_or_initialize(attributes.slice("invoice_id"))
29+
record.update!(attributes)
30+
record
31+
end
32+
end

app/models/freshbooks_payment.rb

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class FreshbooksPayment < ActiveRecord::Base
2+
validates :payment_id, presence: true, uniqueness: true
3+
validates :invoice_id, presence: true
4+
validates :date, presence: true
5+
validates :updated, presence: true
6+
validates :payment_type, presence: true
7+
validates :client_id, presence: true
8+
validates :amount, presence: true
9+
validates :from_credit, presence: true
10+
validates :currency_code, presence: true
11+
12+
FIELDS_TO_IMPORT = %w(
13+
payment_id
14+
invoice_id
15+
client_id
16+
currency_code
17+
amount
18+
from_credit
19+
notes
20+
date
21+
updated
22+
)
23+
24+
def self.import(payment)
25+
attributes = payment.slice(*FIELDS_TO_IMPORT)
26+
attributes["payment_type"] = payment["type"]
27+
28+
gateway = payment["gateway_transaction"]
29+
if gateway
30+
attributes["gateway_reference_id"] = gateway["reference_id"]
31+
attributes["gateway_name"] = gateway["gateway_name"]
32+
end
33+
34+
record = first_or_initialize(attributes.slice("payment_id"))
35+
record.update!(attributes)
36+
record
37+
end
38+
end

app/models/import_freshbooks.rb

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class ImportFreshbooks
2+
attr_reader :client
3+
4+
def initialize(url: ENV['FRESHBOOKS_API_URL'], token: ENV['FRESHBOOKS_AUTH_TOKEN'], client: nil)
5+
@client = client || FreshBooks::Client.new(url, token)
6+
end
7+
8+
def invoices
9+
collect_resource("invoice")
10+
end
11+
12+
def payments
13+
collect_resource("payment")
14+
end
15+
16+
def raw_resource(resource, page)
17+
Rails.logger.info "Fetching #{resource} page #{page}"
18+
@client.send(resource.to_sym, page: page).list[resource.pluralize]
19+
end
20+
21+
def collect_resource(resource, page = 1)
22+
resource_data = raw_resource(resource, page)
23+
resources = resource_data[resource]
24+
max_pages = resource_data["pages"].to_i
25+
Rails.logger.debug "Fetched #{resource} page #{page} of #{max_pages} pages"
26+
return resources if page >= max_pages
27+
resources + collect_resource(resource, page + 1)
28+
end
29+
30+
def import_invoices
31+
invoices.map do |invoice|
32+
FreshbooksInvoice.import(invoice)
33+
end
34+
end
35+
36+
def import_payments
37+
payments.map do |invoice|
38+
FreshbooksPayment.import(invoice)
39+
end
40+
end
41+
end

config/application.yml.sample

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
BLOG_RSS_URL:
1+
BLOG_RSS_URL: http://www.wizard.codes/rss/
22
S3_BUCKET_NAME:
33
AWS_ACCESS_KEY_ID:
44
AWS_SECRET_ACCESS_KEY:
5+
FRESHBOOKS_API_URL: wizarddevelopment.freshbooks.com
6+
FRESHBOOKS_AUTH_TOKEN:

config/environments/development.rb

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
# Print deprecation notices to the Rails logger.
2020
config.active_support.deprecation = :log
21+
# config.log_level = :debug
2122

2223
# Raise an error on page load if there are pending migrations
2324
# config.active_record.migration_error = :page_load

config/environments/production.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
# config.force_ssl = true
4343

4444
# Set to :debug to see everything in the log.
45-
config.log_level = :info
45+
config.log_level = :warn
4646

4747
# Prepend all log lines with the following tags.
4848
# config.log_tags = [ :subdomain, :uuid ]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class CreateFreshbooksInvoice < ActiveRecord::Migration
2+
def change
3+
create_table :freshbooks_invoices do |t|
4+
t.string :invoice_id, null: false
5+
t.string :number, null: false
6+
t.string :organization, null: false
7+
t.string :client_id, null: false
8+
t.string :status, null: false
9+
t.decimal :amount, null: false
10+
t.decimal :amount_outstanding, null: false
11+
t.decimal :paid, null: false
12+
t.string :public_url, null: false
13+
t.date :date, null: false
14+
t.timestamps null: false
15+
end
16+
add_index :freshbooks_invoices, :invoice_id, unique: true
17+
end
18+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class CreateFreshbooksPayments < ActiveRecord::Migration
2+
def change
3+
create_table :freshbooks_payments do |t|
4+
t.string :payment_id, null: false
5+
t.string :invoice_id, null: false
6+
t.string :client_id, null: false
7+
t.string :payment_type, null: false
8+
t.string :currency_code, null: false
9+
t.string :gateway_reference_id
10+
t.string :gateway_name
11+
t.text :notes
12+
t.decimal :amount, null: false
13+
t.decimal :from_credit, null: false
14+
15+
t.date :date, null: false
16+
t.date :updated, null: false
17+
t.timestamps null: false
18+
end
19+
end
20+
end

0 commit comments

Comments
 (0)