billomat 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40a474e94aa0c704209fa2ebd99a4981730be955
4
- data.tar.gz: efc188086b6124410a52c6d6796541a38fddb7af
3
+ metadata.gz: e9b1dc728272e6dca7e6fe43418c9ec7511f962b
4
+ data.tar.gz: a83499376d3e6aa576d4a9270d3d5f3bd3566199
5
5
  SHA512:
6
- metadata.gz: 11510e2136f9f04d213b44459bb9459628c67e38d5a469b9491300ad4f68faef00f8bad55817eb4e88048f4f167aa745607062c41ac15debfeaba631cb477c08
7
- data.tar.gz: cbf6cbb1066541439b77030703b2a5085f0975dbdf7a089ca46e5c0dd2ad8fb4fec789d5091af2a8b77543fa95658176a95cb82ccc41de2533a6e7bad99b0102
6
+ metadata.gz: 4387bcef030751f0147c14469d0b25fc332266c0462be814396ba749ff8ba51c2dd474437d7946d6069ca20c732f516a11bfead7fa31d69b3a4e405b4f5213ca
7
+ data.tar.gz: 7502cfd88d175ed62aa57be385c99dc00b07a03cb49f97cfed3ab6f71214944e9cb3572ee03da6ee5b43102394020a90028a993629fa589bedd01d7e00873d5e
data/.travis.yml CHANGED
@@ -1,5 +1,18 @@
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=a77802032cccc178727a1df1ff1f283a8255959f9a175f20b73b8231ca35da2f
1
4
  sudo: false
2
5
  language: ruby
3
6
  rvm:
4
- - 2.4.1
7
+ - 2.0
8
+ - 2.1
9
+ - 2.2
10
+ - 2.3
11
+ - 2.4
5
12
  before_install: gem install bundler -v 1.15.1
13
+ before_script:
14
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
15
+ - chmod +x ./cc-test-reporter
16
+ - ./cc-test-reporter before-build
17
+ after_script:
18
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Billomat
2
2
  [![Build Status](https://travis-ci.org/hausgold/billomat.svg?branch=master)](https://travis-ci.org/hausgold/billomat)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/49baf848f42a2e5b95db/maintainability)](https://codeclimate.com/github/hausgold/billomat/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/49baf848f42a2e5b95db/test_coverage)](https://codeclimate.com/github/hausgold/billomat/test_coverage)
3
5
 
4
6
  This gem provides a Ruby API for [billomat.com](https://billomat.com) - an online accounting service.
5
7
 
@@ -13,11 +15,15 @@ gem 'billomat'
13
15
 
14
16
  And then execute:
15
17
 
16
- $ bundle
18
+ ```bash
19
+ $ bundle
20
+ ```
17
21
 
18
22
  Or install it yourself as:
19
23
 
20
- $ gem install billomat
24
+ ```bash
25
+ $ gem install billomat
26
+ ```
21
27
 
22
28
  ## Usage
23
29
 
@@ -25,7 +31,7 @@ Or install it yourself as:
25
31
 
26
32
  The configuration takes two settings: `api_key` and `subdomain`. The latter is e.g. the name of your organization.
27
33
 
28
- ```
34
+ ```ruby
29
35
  Billomat.configure do |config|
30
36
  config.subdomain = 'your-company'
31
37
  config.api_key = 'a3b148a61cb642389b4f9953f6233f20'
@@ -36,7 +42,7 @@ end
36
42
 
37
43
  Currently there is basic support for the models `Invoice`, `Client`, `InvoicePayment`, `InvoiceItem`
38
44
 
39
- ```
45
+ ```ruby
40
46
  Billomat::Models::Invoice.where(invoice_number: 'RE1234')
41
47
  => [#<Billomat::Models::Invoice:0x005574b58d6510 ...]
42
48
 
@@ -51,7 +57,6 @@ client.delete
51
57
  => true
52
58
  ```
53
59
 
54
-
55
60
  ## Development
56
61
 
57
62
  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.
@@ -2,17 +2,26 @@
2
2
 
3
3
  module Billomat
4
4
  module Actions
5
+ ##
6
+ # This actions cancels an invoice
5
7
  class Cancel
8
+ # @param [String] invoice_id The invoice ID
9
+ # @return [Billomat::Actions::Cancel]
6
10
  def initialize(invoice_id)
7
11
  @invoice_id = invoice_id
8
12
  end
9
13
 
14
+ ##
15
+ # Calls the gateway
16
+ #
17
+ # @return [TrueClass]
10
18
  def call
11
19
  Billomat::Gateway.new(:put, path).run
12
20
 
13
21
  true
14
22
  end
15
23
 
24
+ # @return [String] The cancel path with the invoice_id
16
25
  def path
17
26
  "/invoices/#{@invoice_id}/cancel"
18
27
  end
@@ -2,22 +2,42 @@
2
2
 
3
3
  module Billomat
4
4
  module Actions
5
+ ##
6
+ # Completes an invoice by calling the /complete path on a resource
5
7
  class Complete
8
+ ##
9
+ # Returns a Complete object
10
+ #
11
+ # @param [String] invoice_id The ID of the invoice
12
+ # @param [Hash] opts The options for this request
13
+ # @return [Billomat::Actions::Complete]
14
+ #
15
+ # @example
16
+ # Billomat::Actions::Complete('12345', { template_id: '10231' })
6
17
  def initialize(invoice_id, opts = {})
7
18
  @invoice_id = invoice_id
8
19
  @opts = opts
9
20
  end
10
21
 
22
+ ##
23
+ # Calls the gateway
24
+ #
25
+ # @return [TrueClass]
11
26
  def call
12
27
  Billomat::Gateway.new(:put, path, wrapped_data).run
13
28
 
14
29
  true
15
30
  end
16
31
 
32
+ ##
33
+ # The given options have to be wrapped
34
+ #
35
+ # @return [Hash] The payload for the complete request
17
36
  def wrapped_data
18
37
  { complete: @opts }
19
38
  end
20
39
 
40
+ # @return [String] The complete path with the invoice_id
21
41
  def path
22
42
  "/invoices/#{@invoice_id}/complete"
23
43
  end
@@ -1,27 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # This actions sends an invoice email
4
- # Recipients must be passed like this:
5
- # { recipients: { to: 'bob@example.org' } }
6
-
7
3
  module Billomat
8
4
  module Actions
5
+ ##
6
+ # This actions sends an invoice email.
7
+ # Recipients must be passed like this:
8
+ # { recipients: { to: 'bob@example.org' } }
9
+ #
10
+ # @example
11
+ # Billomat::Actions::Email.new('1235', { recipiens: { to: 'a@b.org' } })
9
12
  class Email
13
+ # @param [String] invoice_id The invoice ID
14
+ # @param [Hash] opts The options for this action
15
+ #
16
+ # @return [Billomat::Actions::Email]
10
17
  def initialize(invoice_id, opts = {})
11
18
  @invoice_id = invoice_id
12
19
  @opts = opts
13
20
  end
14
21
 
22
+ ##
23
+ # Calls the gateway
24
+ #
25
+ # @return [TrueClass]
15
26
  def call
16
27
  Billomat::Gateway.new(:post, path, wrapped_data).run
17
28
 
18
29
  true
19
30
  end
20
31
 
32
+ ##
33
+ # Wraps the options
34
+ #
35
+ # @return [Hash] The wrapped email options
21
36
  def wrapped_data
22
37
  { email: @opts }
23
38
  end
24
39
 
40
+ # @return [String] The path for the email action
25
41
  def path
26
42
  "/invoices/#{@invoice_id}/email"
27
43
  end
@@ -2,17 +2,32 @@
2
2
 
3
3
  module Billomat
4
4
  module Actions
5
+ ##
6
+ # This class allows to download the invoice as a pdf.
7
+ # The PDF comes in a base64 encoded string in the response body.
5
8
  class Pdf
9
+ # @param [String] invoice_id The invoice ID
10
+ # @param [Hash] opts The options for this action
11
+ #
12
+ # @return [Billomat::Actions::Pdf]
6
13
  def initialize(invoice_id, opts = {})
7
14
  @invoice_id = invoice_id
8
15
  @opts = opts
9
16
  end
10
17
 
18
+ ##
19
+ # Calls the gateway
20
+ #
21
+ # @return [TrueClass]
11
22
  def call
12
23
  resp = Billomat::Gateway.new(:get, path).run
13
24
  resp['pdf']
14
25
  end
15
26
 
27
+ ##
28
+ # Wraps the options
29
+ #
30
+ # @return [Hash] The wrapped email options
16
31
  def path
17
32
  "/invoices/#{@invoice_id}/pdf"
18
33
  end
@@ -2,17 +2,30 @@
2
2
 
3
3
  module Billomat
4
4
  module Actions
5
+ ##
6
+ # This actions uncancels an canceld invoice.
7
+ #
8
+ # @example
9
+ # Billomat::Actions::Uncancel.new('1235')
5
10
  class Uncancel
11
+ # @param [String] invoice_id The invoice ID
12
+ #
13
+ # @return [Billomat::Actions::Uncancel]
6
14
  def initialize(invoice_id)
7
15
  @invoice_id = invoice_id
8
16
  end
9
17
 
18
+ ##
19
+ # Calls the gateway
20
+ #
21
+ # @return [TrueClass]
10
22
  def call
11
23
  Billomat::Gateway.new(:put, path).run
12
24
 
13
25
  true
14
26
  end
15
27
 
28
+ # @return [String] The path for the uncancel action
16
29
  def path
17
30
  "/invoices/#{@invoice_id}/uncancel"
18
31
  end
@@ -7,5 +7,8 @@ require 'billomat/actions/cancel'
7
7
  require 'billomat/actions/uncancel'
8
8
 
9
9
  module Billomat
10
+ ##
11
+ # Actions are API calls that do not directly represent a resource.
12
+ # They are mostly non-RESTful actions that are called on a resources.
10
13
  module Actions; end
11
14
  end
@@ -4,17 +4,34 @@ require 'rest-client'
4
4
  require 'json'
5
5
 
6
6
  module Billomat
7
+ ##
8
+ # Raised if something goes wrong during an API call
7
9
  class GatewayError < StandardError; end
8
10
 
11
+ ##
12
+ # This class can be used by the gem to communicate with the API
9
13
  class Gateway
10
14
  attr_reader :method, :path, :body
11
15
 
16
+ ##
17
+ # Creates a new Gateway
18
+ #
19
+ # @param [Symbol] method The HTTP verb
20
+ # @param [String] path The path of the resource
21
+ # @param [Hash] body The payload for the request
22
+ #
23
+ # @example
24
+ # Billomat::Gateway.new(:get, '/invoices')
25
+ # Billomat::Gateway.new(:post, '/invoices', { 'invoice' => { ... } })
12
26
  def initialize(method, path, body = {})
13
27
  @method = method.to_sym
14
28
  @path = path
15
29
  @body = body
16
30
  end
17
31
 
32
+ ##
33
+ # Executes the API call
34
+ # @return [Hash] The response body
18
35
  def run
19
36
  resp = RestClient::Request.execute(
20
37
  method: method,
@@ -30,14 +47,17 @@ module Billomat
30
47
  JSON.parse(resp.body)
31
48
  end
32
49
 
50
+ # @return [String] The complete URL for the request
33
51
  def url
34
52
  "https://#{config.subdomain}.billomat.net/api#{path}"
35
53
  end
36
54
 
55
+ # @return [Integer]
37
56
  def timeout
38
57
  5
39
58
  end
40
59
 
60
+ # @return [Hash] The headers for the request.
41
61
  def headers
42
62
  {
43
63
  'Accept' => 'application/json',
@@ -46,6 +66,7 @@ module Billomat
46
66
  }
47
67
  end
48
68
 
69
+ # @return [Billomat::Configuration] The global gem configuration
49
70
  def config
50
71
  Billomat.configuration
51
72
  end
@@ -4,28 +4,52 @@ require 'ostruct'
4
4
 
5
5
  module Billomat
6
6
  module Models
7
+ ##
8
+ # This class is the base for all other models (resources).
9
+ # It handles the communication with the gateway to talk to the API.
7
10
  class Base
8
11
  attr_accessor :data
9
12
 
13
+ ##
14
+ # Tries to find the resource for the given id
15
+ #
16
+ # @param [String] id The resource id
17
+ # @return [Billomat::Models::Base, nil] The found resource or nil
10
18
  def self.find(id)
11
19
  return nil if id.nil?
12
20
  resp = Billomat::Gateway.new(:get, "#{base_path}/#{id}").run
13
21
  new(resp[resource_name])
14
22
  end
15
23
 
24
+ ##
25
+ # Allows to query for a record
26
+ #
27
+ # @param [Hash] hash The query parameters
28
+ # @return [Array<Billomat::Models::Base>] The found records
16
29
  def self.where(hash = {})
17
30
  Billomat::Search.new(self, hash).run
18
31
  end
19
32
 
33
+ ##
34
+ # Initializes a new model
35
+ #
36
+ # @param [Hash] data The attributes of the object
37
+ # @return [Billomat::Models::Base] The record as an object
20
38
  def initialize(data = {})
21
39
  @data = OpenStruct.new(data)
22
40
  end
23
41
 
42
+ ##
43
+ # Persists the current object in the API.
44
+ # When record is new it calls create, otherwise it saves the object.
45
+ #
46
+ # @return [TrueClass]
24
47
  def save
25
48
  return create if id.blank?
26
49
  update
27
50
  end
28
51
 
52
+ # @return [TrueClass]
29
53
  def create
30
54
  resp = Billomat::Gateway.new(
31
55
  :post, self.class.base_path, wrapped_data
@@ -36,6 +60,7 @@ module Billomat
36
60
  true
37
61
  end
38
62
 
63
+ # @return [TrueClass]
39
64
  def update
40
65
  path = "#{self.class.base_path}/#{id}"
41
66
  resp = Billomat::Gateway.new(:put, path, wrapped_data).run
@@ -44,6 +69,7 @@ module Billomat
44
69
  true
45
70
  end
46
71
 
72
+ # @return [TrueClass]
47
73
  def delete
48
74
  path = "#{self.class.base_path}/#{id}"
49
75
  Billomat::Gateway.new(:delete, path).run
@@ -51,19 +77,41 @@ module Billomat
51
77
  true
52
78
  end
53
79
 
80
+ # @return [String, nil] The object's ID
54
81
  def id
55
82
  @data['id'] || nil
56
83
  end
57
84
 
85
+ ##
86
+ # Wraps the data so the API accepts the request
87
+ #
88
+ # @example
89
+ # some_invoice.wrapped_data
90
+ # #=> { "invoice" => { "id" => "12345" } }
91
+ #
92
+ # @return [Hash] The wrapped data
58
93
  def wrapped_data
59
94
  { self.class.resource_name => @data.to_h }
60
95
  end
61
96
 
97
+ ##
98
+ # All values in the @data hash can be accessed like a 'normal' method
99
+ #
100
+ # @example
101
+ # invoice = Billomat::Models::Invoice.new(invoice_number: '123')
102
+ # invoice.invoice_number
103
+ # #=> '123'
62
104
  def method_missing(method, *args, &block)
63
105
  return @data[method] if @data.to_h.keys.include?(method)
64
106
  super
65
107
  end
66
108
 
109
+ ##
110
+ # Necessary for method_missing
111
+ #
112
+ # @param [Symbol] method The method name
113
+ # @param [TrueClass, FalseClass] include_privat
114
+ # @return [TrueClass, FalseClass]
67
115
  def respond_to_missing?(method, include_privat = false)
68
116
  @data.to_h.keys.include?(method.to_s) || super
69
117
  end
@@ -2,11 +2,15 @@
2
2
 
3
3
  module Billomat
4
4
  module Models
5
+ ##
6
+ # Representation of the client resource
5
7
  class Client < Base
8
+ # @return [String] The resource's base path
6
9
  def self.base_path
7
10
  '/clients'
8
11
  end
9
12
 
13
+ # @return [String] The resource's name
10
14
  def self.resource_name
11
15
  'client'
12
16
  end
@@ -2,29 +2,43 @@
2
2
 
3
3
  module Billomat
4
4
  module Models
5
+ ##
6
+ # Representation of the invoice resource
5
7
  class Invoice < Base
8
+ # @return [String] The resource's base path
6
9
  def self.base_path
7
10
  '/invoices'
8
11
  end
9
12
 
13
+ # @return [String] The resource's name
10
14
  def self.resource_name
11
15
  'invoice'
12
16
  end
13
17
 
18
+ ##
19
+ # Completes the invoice by calling the Complete action
14
20
  def complete!
15
21
  Billomat::Actions::Complete.new(id).call
16
22
  end
17
23
 
24
+ ##
25
+ # Cancels the invoice by calling the Cancel action
18
26
  def cancel!
19
27
  Billomat::Actions::Cancel.new(id).call
20
28
  end
21
29
 
30
+ ##
31
+ # Sends the invoice as an email to the given recipient
32
+ #
33
+ # @param [String] recipient The email address of the recipient
22
34
  def send_email(recipient)
23
35
  email_params = { recipients: { to: recipient } }
24
36
 
25
37
  Billomat::Actions::Email.new(id, email_params).call
26
38
  end
27
39
 
40
+ ##
41
+ # Allows to download the invoice as an PDF
28
42
  def to_pdf
29
43
  Billomat::Actions::Pdf.new(id).call
30
44
  end
@@ -2,11 +2,15 @@
2
2
 
3
3
  module Billomat
4
4
  module Models
5
+ ##
6
+ # Representation of the invoice item resource
5
7
  class InvoiceItem < Base
8
+ # @return [String] The resource's base path
6
9
  def self.base_path
7
10
  '/invoice-items'
8
11
  end
9
12
 
13
+ # @return [String] The resource's name
10
14
  def self.resource_name
11
15
  'invoice-item'
12
16
  end
@@ -2,11 +2,15 @@
2
2
 
3
3
  module Billomat
4
4
  module Models
5
+ ##
6
+ # Representation of the invoice payment resource
5
7
  class InvoicePayment < Base
8
+ # @return [String] The resource's base path
6
9
  def self.base_path
7
10
  '/invoice-payments'
8
11
  end
9
12
 
13
+ # @return [String] The resource's name
10
14
  def self.resource_name
11
15
  'invoice-payment'
12
16
  end
@@ -7,5 +7,7 @@ require 'billomat/models/invoice_item'
7
7
  require 'billomat/models/invoice_payment'
8
8
 
9
9
  module Billomat
10
+ ##
11
+ # Models represent a resource in the API, e.g. invoices, clients
10
12
  module Models; end
11
13
  end
@@ -3,21 +3,41 @@
3
3
  require 'uri'
4
4
 
5
5
  module Billomat
6
+ ##
7
+ # This class provides the possibility to query the resources
6
8
  class Search
9
+ ##
10
+ # Creates a new search object
11
+ #
12
+ # @param [Class] resource The resource class to be queried
13
+ # @param [Hash] hash The query
7
14
  def initialize(resource, hash)
8
15
  @resource = resource
9
16
  @hash = hash
10
17
  end
11
18
 
19
+ # @return [String] The path including the query
12
20
  def path
13
21
  "#{@resource.base_path}?#{hash_to_query}"
14
22
  end
15
23
 
24
+ ##
25
+ # Runs the query and calls the gateway
26
+ #
27
+ # @return [Array<Billomat::Model::Base>]
16
28
  def run
17
- return [] if @hash.compact.empty?
29
+ return [] if @hash.reject { |k, v| v.nil? }.empty?
18
30
  to_array(Billomat::Gateway.new(:get, path).run)
19
31
  end
20
32
 
33
+ ##
34
+ # Corrects the response to always return an array
35
+ #
36
+ # @todo Due to a strange API behaviour we have to fix the reponse here.
37
+ # This may be fixed in a new API version.
38
+ #
39
+ # @param [Hash] resp The response from the gateway
40
+ # @return [Array<Billomat::Model::Base>]
21
41
  def to_array(resp)
22
42
  case count(resp)
23
43
  when 0
@@ -32,10 +52,13 @@ module Billomat
32
52
  end
33
53
  end
34
54
 
55
+ # @return [String] The name of the resource
35
56
  def name
36
57
  @resource.resource_name
37
58
  end
38
59
 
60
+ # @param [Hash] resp The response from the gateway
61
+ # @return [Integer] The number of records found
39
62
  def count(resp)
40
63
  return 0 if resp.nil?
41
64
  resp["#{name}s"]['@total'].to_i
@@ -43,6 +66,7 @@ module Billomat
43
66
 
44
67
  private
45
68
 
69
+ # @return [String] The query as www encoded string
46
70
  def hash_to_query
47
71
  URI.encode_www_form(@hash)
48
72
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Billomat
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/billomat.rb CHANGED
@@ -7,15 +7,27 @@ require 'billomat/actions'
7
7
  require 'billomat/search'
8
8
  require 'billomat/gateway'
9
9
 
10
+ ##
11
+ # An wrapper for the
12
+ # <a href="https://billomat.com">Billomat</a>
13
+ # API
10
14
  module Billomat
11
15
  class << self
12
16
  attr_writer :configuration
13
17
  end
14
18
 
19
+ # @return [Billomat::Configuration] The global billomat configuration
15
20
  def self.configuration
16
21
  @configuration ||= Billomat::Configuration.new
17
22
  end
18
23
 
24
+ # Class method to set and change the global configuration
25
+ #
26
+ # @example
27
+ # Billomat.configure do |config|
28
+ # config.subdomain = 'your-business-name'
29
+ # config.api_key = 'a3b148a61cb642389b4f9953f6233f20'
30
+ # end
19
31
  def self.configure
20
32
  yield(configuration)
21
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: billomat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Vogt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-05 00:00:00.000000000 Z
11
+ date: 2017-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client