codat 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92ae19ae782d5a282bfe31ac82a20578fe5f69c7ddf3db320580e4d23af4a511
4
- data.tar.gz: c76eb6c58326f6bc12b8c6b2bdb622541e5dd93ac07c3e369af0d59b01004488
3
+ metadata.gz: c200bf7bf3b3702f186640149441c8cdb016b2078e374f8386da4f36d6d14a5a
4
+ data.tar.gz: 0b2409f51c5a5d6c49b3f477d8d9613a759071f207fcc0359f10b75a976b62af
5
5
  SHA512:
6
- metadata.gz: c4f2c95fb7cdd9c33f059ea0892af826e3c9b24aeec3f01a300fbf3633d4f7a1a4dad3d6b73680035ab0fd6b669e2d4aede3cb3e66ee8de5fe6153ad7ba4f68c
7
- data.tar.gz: 6548792832997f953b496bc7e108ea67f6efe334e45e06f81389ef8d6d9f29e1555bf387467b5fb72a40d0cf77c49089b920c6ca8b32c250140c213a6a0ae11d
6
+ metadata.gz: 2bb60e32a71c375260ad46d6da81505068b9a18dbdeb256674c204d56fcacd7797779109cf7c115a3fb1ce3e46d6c671df9358cf491cb9a8c15c0aa40902b71c
7
+ data.tar.gz: f8a0417775eefeefc554f593542f88d296e61f9dd614a015a45b1b72f3981218c6b461530f0960da6509c35d4558a4c9dc3b13d7be0d8d4b36d4ead46bc644f7
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ Gemfile.lock
10
11
 
11
12
  # rspec failure tracking
12
13
  .rspec_status
data/README.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Codat
2
2
 
3
+ A simple wrapper for the [Codat](https://www.codat.io/) API. Please refer to Codat's documentation
4
+ to complement any information you need:
5
+
6
+ * [Codat API reference](https://docs.codat.io/)
7
+ * [Codat API explorer](https://api-uat.codat.io/swagger/ui/index) (to use this you need to have
8
+ access to the UAT portal).
9
+
3
10
  ## Installation
4
11
 
5
12
  Add this line to your application's Gemfile:
@@ -23,50 +30,50 @@ Or install it yourself as:
23
30
  To get a list of bank accounts:
24
31
 
25
32
  ```ruby
26
- list = BankAccount.all(company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac')
33
+ BankAccount.all(company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac')
27
34
  # => []
28
35
  ```
29
36
 
30
- ### Financial financials
37
+ ### Financial reports
31
38
 
32
- To get a financial reports - profit & loss:
39
+ To get a financial report - profit & loss:
33
40
 
34
41
  ```ruby
35
- list = Financial.profit_and_loss(
36
- company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac',
37
- period_length: '2',
38
- periods_to_compare: '2'
42
+ ProfitAndLoss.find(
43
+ company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac',
44
+ period_length: 12,
45
+ periods_to_compare: 2
39
46
  )
40
47
  # => []
41
48
  ```
42
49
 
43
- To get a financial reports - balance sheet:
50
+ To get a financial report - balance sheet:
44
51
 
45
52
  ```ruby
46
- list = BankAccount.balance_sheet(
47
- company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac',
48
- period_length: period_length,
49
- periods_to_compare: periods_to_compare
53
+ BalanceSheet.find(
54
+ company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac',
55
+ period_length: 12,
56
+ periods_to_compare: 2
50
57
  )
51
58
  ```
52
59
 
53
- ### Company companies
60
+ ### Companies
54
61
 
55
62
  To get a list of companies (paginated):
56
63
 
57
64
  ```ruby
58
- list = Company.all(page: '1')
65
+ Company.all(page: 1)
59
66
  # => []
60
67
  ```
61
68
 
62
69
  To create a company:
63
70
 
64
71
  ```ruby
65
- response = Company.create(name: 'company name')
72
+ Company.create(name: 'company name')
66
73
  # => {}
67
74
  ```
68
75
 
69
- ### Report reports
76
+ ### Report
70
77
 
71
78
  To get a list of reports for aged debtor:
72
79
 
@@ -75,7 +82,7 @@ list = Report.all(company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac')
75
82
  # => []
76
83
  ```
77
84
 
78
- ### BankStatement bankStatements
85
+ ### BankStatement
79
86
 
80
87
  To get a list of bank statements:
81
88
 
@@ -86,9 +93,14 @@ list = BankStatement.all(company_id: 'a49b891d-a593-43aa-bb82-0d8b108eb3ac')
86
93
 
87
94
  ## Development
88
95
 
89
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
96
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run
97
+ the tests. You can also run `bin/console` for an interactive prompt that will allow you to
98
+ experiment.
90
99
 
91
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
100
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new
101
+ version, update the version number in `version.rb`, and then run `bundle exec rake release`, which
102
+ will create a git tag for the version, push git commits and tags, and push the `.gem` file to
103
+ [rubygems.org](https://rubygems.org).
92
104
 
93
105
  ## Contributing
94
106
 
@@ -5,10 +5,11 @@ require 'codat/configuration'
5
5
  require 'codat/client'
6
6
 
7
7
  require 'codat/models/bank_account'
8
- require 'codat/models/financial'
9
8
  require 'codat/models/company'
10
9
  require 'codat/models/report'
11
10
  require 'codat/models/bank_statement'
11
+ require 'codat/models/balance_sheet'
12
+ require 'codat/models/profit_and_loss'
12
13
 
13
14
  module Codat
14
15
  module_function
@@ -7,9 +7,6 @@ module Codat
7
7
  class GenericError < StandardError
8
8
  end
9
9
 
10
- class CompanyNotProvidedError < StandardError
11
- end
12
-
13
10
  class InvalidRequestError < StandardError
14
11
  end
15
12
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'codat/base_model'
4
+ require 'codat/models/balance_sheet_report'
5
+ require 'codat/models/financial_sheet'
6
+
7
+ module Codat
8
+ module Models
9
+ class BalanceSheet < FinancialSheet
10
+ endpoint '/companies/:company_id/data/financials/balanceSheet'
11
+
12
+ # attributes :currency, :most_recent_available_month, :earliest_available_month
13
+
14
+ report_class BalanceSheetReport
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'codat/base_model'
5
+ require 'codat/models/report_item'
6
+
7
+ module Codat
8
+ module Models
9
+ class BalanceSheetReport < BaseModel
10
+ attributes :date, :net_assets
11
+
12
+ attr_accessor :assets, :liabilities, :equity
13
+
14
+ def initialize(json: {})
15
+ super
16
+
17
+ @assets = ReportItem.new(json: json.fetch(:assets, {}))
18
+ @liabilities = ReportItem.new(json: json.fetch(:liabilities, {}))
19
+ @equity = ReportItem.new(json: json.fetch(:equity, {}))
20
+ end
21
+
22
+ def date
23
+ Date.parse(@date)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -6,21 +6,23 @@ module Codat
6
6
  module Models
7
7
  # Bank statements for a given company.
8
8
  class BankStatement < BaseModel
9
- ENDPOINT = '/companies/:company_id/data/bankStatements/accounts'
9
+ ENDPOINT = '/companies/:company_id/data/bankStatements'
10
10
 
11
11
  attributes :id, :date, :description, :reconciled, :amount, :balance, :transaction_type
12
12
  attributes :modified_date, :source_modifiedDate
13
13
 
14
- def self.all(company_id:)
15
- url = format_url(
16
- ENDPOINT, company_id: company_id.to_s.strip
17
- )
14
+ def self.all(company_id:, account_id:, page: 1)
15
+ url = format_url(ENDPOINT, company_id: company_id.to_s.strip)
18
16
 
19
- result = get(url)
17
+ result = get(url, accountId: account_id.to_s.strip, page: page.to_s.strip)
20
18
 
21
19
  return [] if result.status == 404
22
20
 
23
- result.body.map { |bank_statement| new(json: bank_statement) }
21
+ records = result.body.dig(:results)
22
+
23
+ return [] unless records
24
+
25
+ records.map { |bank_statement| new(json: bank_statement) }
24
26
  end
25
27
  end
26
28
  end
@@ -6,13 +6,17 @@ module Codat
6
6
  module Models
7
7
  # Companies for a given company.
8
8
  class Company < BaseModel
9
- ENDPOINT = '/companies'
9
+ ENDPOINTS = {
10
+ collection: '/companies',
11
+ single: '/companies/:company_id'
12
+ }.freeze
10
13
 
11
14
  attributes :id, :name, :platform, :redirect, :status, :last_sync, :data_connections
12
15
  attributes :integration_id, :source_id, :platform_name, :link_url
13
16
 
17
+ # Returns the list of companies in the Codat account.
14
18
  def self.all(params = {})
15
- result = get(ENDPOINT, params)
19
+ result = get(ENDPOINTS[:collection], params)
16
20
 
17
21
  return [] if result.status == 404
18
22
 
@@ -21,10 +25,18 @@ module Codat
21
25
  result.body[:results].map { |company| new(json: company) }
22
26
  end
23
27
 
24
- def self.create(params = {})
25
- url = format_url(ENDPOINT, {})
28
+ def self.find(company_id)
29
+ url = format_url(ENDPOINTS[:single], company_id: company_id)
30
+
31
+ result = get(url)
26
32
 
27
- result = post(url, params)
33
+ return nil if result.status == 404
34
+
35
+ new(json: result.body)
36
+ end
37
+
38
+ def self.create(params = {})
39
+ result = post(ENDPOINTS[:collection], params)
28
40
 
29
41
  return { error: 'An error occured.' } if result.status == 404 || result.status == 400
30
42
 
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module Codat
6
+ module Models
7
+ class FinancialSheet < BaseModel
8
+ # Default period length (months)
9
+ DEFAULT_PERIOD_LENGTH = 12
10
+
11
+ # Default number of periods to compare
12
+ DEFAULT_PERIODS_TO_COMPARE = 2
13
+
14
+ attr_reader :reports
15
+
16
+ def self.inherited(other)
17
+ other.attributes :currency, :most_recent_available_month, :earliest_available_month
18
+ end
19
+
20
+ # Finds the latest financial sheet for a company. This can be a balance sheet or a profit and
21
+ # loss document.
22
+ #
23
+ # Params are listed below:
24
+ # * company_id - the company ID from Codat
25
+ # * period_length - the number of months to get
26
+ # * periods_to_compare - how many periods (of period_length size) you want
27
+ # * start_month (optional) - starting in which month (date)
28
+ #
29
+ # An ArgumentError is raised unless you provide a :company_id key in the params.
30
+ def self.find(params = {})
31
+ company_id = params.dig(:company_id)
32
+
33
+ raise ArgumentError, 'please provide company_id' unless company_id
34
+
35
+ url = format_url(@endpoint, company_id: company_id.to_s.strip)
36
+
37
+ result = get(url, build_query(params))
38
+
39
+ return nil if result.status == 404 || result.status == 400
40
+
41
+ new(json: result.body)
42
+ end
43
+
44
+ def self.build_query(params)
45
+ options = params.dup
46
+
47
+ query = {
48
+ periodLength: options.fetch(:period_length, DEFAULT_PERIOD_LENGTH),
49
+ periodsToCompare: options.fetch(:periods_to_compare, DEFAULT_PERIODS_TO_COMPARE)
50
+ }
51
+
52
+ options = options.map { |key, value| [Camelizer.transform(key), value] }.to_h
53
+
54
+ query.merge(options)
55
+ end
56
+
57
+ def self.report_class(report_class = nil)
58
+ return @report_class unless report_class
59
+
60
+ @report_class = report_class
61
+ end
62
+
63
+ def self.endpoint(endpoint = nil)
64
+ return @endpoint unless endpoint
65
+
66
+ @endpoint = endpoint
67
+ end
68
+
69
+ def initialize(json: {})
70
+ super
71
+
72
+ @most_recent_available_month = Date.parse(json.dig(:mostRecentAvailableMonth))
73
+ @earliest_available_month = Date.parse(json.dig(:earliestAvailableMonth))
74
+
75
+ reports_json = json.fetch(:reports, {})
76
+ @reports = reports_json.map { |report| self.class.report_class.new(json: report) }
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'codat/base_model'
4
+ require 'codat/models/profit_and_loss_report'
5
+ require 'codat/models/financial_sheet'
6
+
7
+ module Codat
8
+ module Models
9
+ class ProfitAndLoss < FinancialSheet
10
+ endpoint '/companies/:company_id/data/financials/profitAndLoss'
11
+
12
+ attributes :report_basis
13
+
14
+ report_class ProfitAndLossReport
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+ require 'codat/base_model'
5
+ require 'codat/models/report_item'
6
+
7
+ module Codat
8
+ module Models
9
+ class ProfitAndLossReport < BaseModel
10
+ attributes :from_date, :to_date, :gross_profit, :net_other_income, :net_profit
11
+ attributes :net_operating_profit
12
+
13
+ attr_accessor :income, :cost_of_sales, :expenses, :other_expenses, :other_income
14
+
15
+ def initialize(json: {})
16
+ super
17
+
18
+ @from_date = Date.parse(json.fetch(:fromDate))
19
+ @to_date = Date.parse(json.fetch(:toDate))
20
+
21
+ @income = ReportItem.new(json: json.fetch(:income, {}))
22
+ @cost_of_sales = ReportItem.new(json: json.fetch(:costOfSales, {}))
23
+ @expenses = ReportItem.new(json: json.fetch(:expenses, {}))
24
+ @other_expenses = ReportItem.new(json: json.fetch(:otherExpenses, {}))
25
+ @other_income = ReportItem.new(json: json.fetch(:otherIncome, {}))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'codat/base_model'
4
+
5
+ module Codat
6
+ module Models
7
+ # A report item can be present in BalanceSheetReport or ProfitAndLossReport.
8
+ class ReportItem < BaseModel
9
+ attributes :account_id, :name, :value
10
+
11
+ attr_accessor :items
12
+
13
+ def initialize(json: {})
14
+ super
15
+
16
+ # The items can have an array of items inside. It's weird, but this happens a lot.
17
+ items_json = json.fetch(:items, [])
18
+ @items = items_json.map { |item| ReportItem.new(json: item) }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Codat
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ricardo Otero
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-09-29 00:00:00.000000000 Z
11
+ date: 2018-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -233,7 +233,6 @@ files:
233
233
  - ".rubocop.yml"
234
234
  - ".travis.yml"
235
235
  - Gemfile
236
- - Gemfile.lock
237
236
  - LICENSE.txt
238
237
  - README.md
239
238
  - Rakefile
@@ -247,11 +246,16 @@ files:
247
246
  - lib/codat/configuration.rb
248
247
  - lib/codat/errors.rb
249
248
  - lib/codat/faraday_codat_auth.rb
249
+ - lib/codat/models/balance_sheet.rb
250
+ - lib/codat/models/balance_sheet_report.rb
250
251
  - lib/codat/models/bank_account.rb
251
252
  - lib/codat/models/bank_statement.rb
252
253
  - lib/codat/models/company.rb
253
- - lib/codat/models/financial.rb
254
+ - lib/codat/models/financial_sheet.rb
255
+ - lib/codat/models/profit_and_loss.rb
256
+ - lib/codat/models/profit_and_loss_report.rb
254
257
  - lib/codat/models/report.rb
258
+ - lib/codat/models/report_item.rb
255
259
  - lib/codat/version.rb
256
260
  homepage: https://gitlab.com/finpoint/codat
257
261
  licenses:
@@ -1,104 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- codat (0.1.1)
5
- faraday (~> 0.15)
6
- faraday_middleware (~> 0.12)
7
- faraday_middleware-multi_json (~> 0.0.6)
8
- multi_json (~> 1.13)
9
- rainbow (~> 3.0)
10
-
11
- GEM
12
- remote: https://rubygems.org/
13
- specs:
14
- addressable (2.5.2)
15
- public_suffix (>= 2.0.2, < 4.0)
16
- ast (2.4.0)
17
- byebug (10.0.2)
18
- coderay (1.1.2)
19
- crack (0.4.3)
20
- safe_yaml (~> 1.0.0)
21
- diff-lcs (1.3)
22
- docile (1.3.1)
23
- dotenv (2.5.0)
24
- faraday (0.15.3)
25
- multipart-post (>= 1.2, < 3)
26
- faraday_middleware (0.12.2)
27
- faraday (>= 0.7.4, < 1.0)
28
- faraday_middleware-multi_json (0.0.6)
29
- faraday_middleware
30
- multi_json
31
- hashdiff (0.3.7)
32
- jaro_winkler (1.5.1)
33
- json (2.1.0)
34
- method_source (0.9.0)
35
- multi_json (1.13.1)
36
- multipart-post (2.0.0)
37
- parallel (1.12.1)
38
- parser (2.5.1.2)
39
- ast (~> 2.4.0)
40
- powerpack (0.1.2)
41
- pry (0.11.3)
42
- coderay (~> 1.1.0)
43
- method_source (~> 0.9.0)
44
- pry-byebug (3.6.0)
45
- byebug (~> 10.0)
46
- pry (~> 0.10)
47
- public_suffix (3.0.3)
48
- rainbow (3.0.0)
49
- rake (10.5.0)
50
- rspec (3.8.0)
51
- rspec-core (~> 3.8.0)
52
- rspec-expectations (~> 3.8.0)
53
- rspec-mocks (~> 3.8.0)
54
- rspec-core (3.8.0)
55
- rspec-support (~> 3.8.0)
56
- rspec-expectations (3.8.1)
57
- diff-lcs (>= 1.2.0, < 2.0)
58
- rspec-support (~> 3.8.0)
59
- rspec-mocks (3.8.0)
60
- diff-lcs (>= 1.2.0, < 2.0)
61
- rspec-support (~> 3.8.0)
62
- rspec-support (3.8.0)
63
- rubocop (0.59.2)
64
- jaro_winkler (~> 1.5.1)
65
- parallel (~> 1.10)
66
- parser (>= 2.5, != 2.5.1.1)
67
- powerpack (~> 0.1)
68
- rainbow (>= 2.2.2, < 4.0)
69
- ruby-progressbar (~> 1.7)
70
- unicode-display_width (~> 1.0, >= 1.0.1)
71
- rubocop-rspec (1.29.1)
72
- rubocop (>= 0.58.0)
73
- ruby-progressbar (1.10.0)
74
- safe_yaml (1.0.4)
75
- simplecov (0.16.1)
76
- docile (~> 1.1)
77
- json (>= 1.8, < 3)
78
- simplecov-html (~> 0.10.0)
79
- simplecov-html (0.10.2)
80
- unicode-display_width (1.4.0)
81
- vcr (4.0.0)
82
- webmock (3.4.2)
83
- addressable (>= 2.3.6)
84
- crack (>= 0.3.2)
85
- hashdiff
86
-
87
- PLATFORMS
88
- ruby
89
-
90
- DEPENDENCIES
91
- bundler (~> 1.16)
92
- codat!
93
- dotenv (~> 2.5)
94
- pry-byebug (~> 3.6)
95
- rake (~> 10.0)
96
- rspec (~> 3.0)
97
- rubocop (~> 0.58)
98
- rubocop-rspec (~> 1.27)
99
- simplecov (~> 0.16)
100
- vcr (~> 4.0.0)
101
- webmock (~> 3.4.2)
102
-
103
- BUNDLED WITH
104
- 1.16.1
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'codat/base_model'
4
-
5
- module Codat
6
- module Models
7
- # Financials for a given company.
8
- class Financial < BaseModel
9
- ENDPOINT = {
10
- profit_and_loss: '/companies/:company_id/data/financials/profitAndLoss',
11
- balance_sheet: '/companies/:company_id/data/financials/balanceSheet'
12
- }.freeze
13
-
14
- attributes :from_date, :to_date, :income, :account_id, :name, :value, :items
15
- attributes :cost_of_sales, :gross_profit, :expenses, :net_operating_profit, :other_expenses
16
- attributes :other_income, :net_other_income, :net_profit
17
-
18
- def self.profit_and_loss(params = {})
19
- company_id = params.delete(:company_id)
20
-
21
- raise CompanyNotProvidedError if company_id.nil? || company_id.empty?
22
-
23
- url = format_url(
24
- ENDPOINT[:profit_and_loss],
25
- company_id: company_id.to_s.strip
26
- )
27
-
28
- params = params.map { |key, value| [Camelizer.transform(key), value] }.to_h
29
-
30
- result = get(url, params)
31
-
32
- return [] if result.status == 404 || result.status == 400
33
-
34
- result.body[:reports].map { |report| new(json: report) }
35
- end
36
-
37
- def self.balance_sheet(params = {})
38
- company_id = params.delete(:company_id)
39
-
40
- raise CompanyNotProvidedError if company_id.nil? || company_id.empty?
41
-
42
- url = format_url(
43
- ENDPOINT[:balance_sheet],
44
- company_id: company_id.to_s.strip
45
- )
46
-
47
- params.delete(:company_id)
48
- params = params.map { |key, value| [Camelizer.transform(key), value] }.to_h
49
-
50
- result = get(url, params)
51
-
52
- return [] if result.status == 404 || result.status == 400
53
-
54
- result.body[:reports].map { |report| new(json: report) }
55
- end
56
- end
57
- end
58
- end