fs_api 0.7.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ca3bb7dc2c987a120ce68ac01b80eab0b7b3019a
4
+ data.tar.gz: 970a45f66ea754a021d2849d57dfd34ee423a40a
5
+ SHA512:
6
+ metadata.gz: c639cc53020597dfc81fcbc366aacd5d73dd1ae213ef715c7a73355f15004f41e3ef0080a191f43dc6836f91cb8d630bb888d8df806f28f22a0e4b70237e0379
7
+ data.tar.gz: 89b839e992d6671db8359e023750600202456a1dfd24e44792f1f490913778ce77a3cd18c49a55ecd7f60ea72c27a699972c47d45a0277f3fbab31a082e53099
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.kick ADDED
@@ -0,0 +1,16 @@
1
+ require 'set'
2
+ require 'benchmark'
3
+
4
+ process do |file, flags|
5
+ test_files = Set.new
6
+ case file
7
+ when %r(^spec/.*_spec.rb$)
8
+ test_files << file
9
+ when %r(^lib/(.*).rb)
10
+ test_files << 'spec/lib/' + $1 + '_spec.rb'
11
+ end
12
+ test_files = test_files.select { |filename| File.exist?(filename) }
13
+ unless test_files.empty?
14
+ watcher.execute("bundle exec rspec --fail-fast #{test_files.to_a.join(' ')}")
15
+ end
16
+ end
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --profile
3
+ --order rand
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fs_api.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Maarten van Vliet
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # FsApi
2
+
3
+ Gem to interface with the [factuursturen.nl](https://www.factuursturen.nl/?a=1552)
4
+ invoicing API
5
+
6
+ Still some issues, upon api calls the server sends back json with stringified
7
+ floats/integers/booleans ("true", "1" etc.), for the booleans a conversion is
8
+ in place, for the others there isn't yet.
9
+
10
+ Use the docs at https://www.factuursturen.nl/docs/api_v1.pdf for more information
11
+ on the api. Note that there are inconsistencies between the docs and the
12
+ implementation.
13
+
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'fs_api'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install fs_api
30
+
31
+ ## Usage
32
+
33
+ ```ruby
34
+ api_client = FsApi::Client.new(username, api_key)
35
+
36
+ # Retrieve all products
37
+ api_client.products.all
38
+
39
+ # Retrieve all clients
40
+ api_client.clients.all
41
+
42
+ # Retrieve all invoices
43
+ api_client.invoices.all
44
+
45
+ # Create an invoice
46
+ invoice = api_client.invoices.build({clientnr: '1'})
47
+ api_client.invoices.save(invoice)
48
+
49
+ # or shorthand
50
+ invoice = api_client.invoices.create({clientnr: '1'})
51
+
52
+ # Returns false when it fails
53
+ api_client.invoices.save(invoice)
54
+
55
+ # Has the errors of the last api operation
56
+ invoice.errors
57
+
58
+ # Find an invoice
59
+ api_client.invoices.find(invoice_number)
60
+
61
+ ```
62
+
63
+ ## Todo
64
+ * Handle rate limiting
65
+ * Implement saved invoices resource
66
+ * Implement search
67
+ * Implement invoice payment registration
68
+
69
+ ## Contributing
70
+
71
+ 1. Fork it ( https://github.com/maartenvanvliet/fs_api/fork )
72
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 4. Push to the branch (`git push origin my-new-feature`)
75
+ 5. Create a new Pull Request
data/fs_api.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fs_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fs_api"
8
+ spec.version = FsApi::VERSION
9
+ spec.authors = ["Maarten van Vliet"]
10
+ spec.email = ["maartenvanvliet@gmail.com"]
11
+ spec.summary = %q{Ruby-Api library for factuursturen.nl }
12
+ spec.description = %q{Ruby-Api library for factuursturen.nl. As of yet incomplete support for the api, but functional }
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "rspec", "~> 3.2"
22
+ spec.add_development_dependency "webmock", "~> 1.21"
23
+ end
@@ -0,0 +1,78 @@
1
+ class FsApi::Client
2
+ attr_reader :username, :password, :_last_response
3
+ attr_accessor :errors
4
+
5
+ def initialize(username, password)
6
+ @username = username
7
+ @password = password
8
+ end
9
+
10
+ def base_url
11
+ "https://www.factuursturen.nl:443/api/v1"
12
+ end
13
+
14
+ def http
15
+ @http ||= begin
16
+ uri = uri_for_path(base_url)
17
+ http = Net::HTTP.new(uri.host, uri.port)
18
+ http.use_ssl = uri.scheme == 'https'
19
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
20
+ http
21
+ end
22
+ end
23
+
24
+ def headers
25
+ {
26
+ 'Accept' => 'application/json',
27
+ 'Content-Type' => 'application/json'
28
+ }
29
+ end
30
+
31
+ def uri_for_path(path)
32
+ URI.parse(File.join(base_url, path))
33
+ end
34
+
35
+ def get(path, headers={})
36
+ uri = uri_for_path(path)
37
+ http = Net::HTTP::Get.new(uri.request_uri, self.headers.merge(headers))
38
+ perform(http)
39
+ end
40
+
41
+ def put(path, body=nil, headers={})
42
+ uri = uri_for_path(path)
43
+ http = Net::HTTP::Put.new(uri.request_uri, self.headers.merge(headers))
44
+ http.body = body
45
+ perform(http)
46
+ end
47
+
48
+ def post(path, body=nil, headers={})
49
+ uri = uri_for_path(path)
50
+ http = Net::HTTP::Post.new(uri.request_uri, self.headers.merge(headers))
51
+ http.body = body
52
+ perform(http)
53
+ end
54
+
55
+ def delete(path, headers={})
56
+ uri = uri_for_path(path)
57
+ http = Net::HTTP::Delete.new(uri.request_uri, self.headers.merge(headers))
58
+ perform(http)
59
+ end
60
+
61
+ def invoices
62
+ FsApi::Service::Invoice.new(self)
63
+ end
64
+
65
+ def clients
66
+ FsApi::Service::Client.new(self)
67
+ end
68
+
69
+ def products
70
+ FsApi::Service::Product.new(self)
71
+ end
72
+
73
+ private
74
+ def perform(request)
75
+ request.basic_auth username, password
76
+ @_last_response = http.request(request)
77
+ end
78
+ end
@@ -0,0 +1,58 @@
1
+ class FsApi::Resource::Client
2
+ include FsApi::Resource
3
+ extend FsApi::Resource::ClassMethods
4
+
5
+ has_attributes %i(
6
+ clientnr
7
+ contact
8
+ showcontact
9
+ company
10
+ address
11
+ zipcode
12
+ city
13
+ country
14
+ phone
15
+ mobile
16
+ email
17
+ bankcode
18
+ biccode
19
+ taxnumber
20
+ tax_shifted
21
+ lastinvoice
22
+ sendmethod
23
+ paymentmethod
24
+ top
25
+ stddiscount
26
+ mailintro
27
+ reference
28
+ notes
29
+ notes_on_invoice
30
+ active
31
+ default_doclang
32
+ default_email
33
+ currency
34
+ mandate_id
35
+ mandate_date
36
+ collecttype
37
+ tax_type
38
+ default_category
39
+ )
40
+ has_nillable_attributes %i(
41
+ biccode
42
+ default_doclang
43
+ )
44
+
45
+ has_boolean_attributes %w(
46
+ showcontact
47
+ notes_on_invoice
48
+ active
49
+ tax_shifted
50
+ )
51
+
52
+ has_datetime_attributes %w(
53
+ timestamp
54
+ )
55
+ def path
56
+ "/clients/#{clientnr}"
57
+ end
58
+ end
@@ -0,0 +1,57 @@
1
+ class FsApi::Resource::Invoice
2
+ include FsApi::Resource
3
+ extend FsApi::Resource::ClassMethods
4
+
5
+ has_attributes %i(
6
+ id
7
+ invoicenr_full
8
+ invoicenr
9
+ reference
10
+ lines
11
+ profile
12
+ discounttype
13
+ discount
14
+ paymentcondition
15
+ paymentperiod
16
+ collection
17
+ tax
18
+ totalintax
19
+ clientnr
20
+ company
21
+ contact
22
+ address
23
+ zipcode
24
+ city
25
+ country
26
+ phone
27
+ mobile
28
+ email
29
+ taxnumber
30
+ invoicenote
31
+ sent
32
+ uncollectible
33
+ lastreminder
34
+ open
35
+ paiddate
36
+ taxes
37
+ payment_url
38
+ duedate
39
+ history
40
+ action
41
+ savename
42
+ sendmethod
43
+ )
44
+
45
+ has_datetime_attributes %w(
46
+ duedate
47
+ )
48
+ def path
49
+ "/invoices/#{id}"
50
+ end
51
+
52
+
53
+ # invoices cannot be updated
54
+ def updateable?
55
+ false
56
+ end
57
+ end
@@ -0,0 +1,18 @@
1
+ class FsApi::Resource::Product
2
+ include FsApi::Resource
3
+ extend FsApi::Resource::ClassMethods
4
+
5
+ has_attributes %i(
6
+ id
7
+ code
8
+ name
9
+ price
10
+ priceintax
11
+ taxes
12
+ )
13
+
14
+ def path
15
+ "/products/#{id}"
16
+ end
17
+
18
+ end
@@ -0,0 +1,100 @@
1
+ module FsApi
2
+ module Resource
3
+ attr_reader :attributes
4
+ attr_accessor :errors
5
+
6
+ def initialize(attributes)
7
+ self.attributes = attributes
8
+ end
9
+
10
+ def attributes=(attributes)
11
+ @attributes = attributes
12
+ attributes.each do |attribute, value|
13
+ if respond_to?(writer = attribute.to_s + '=')
14
+ send(writer, value)
15
+ else
16
+ raise "#{self.class} does not have an `#{attribute}' attribute"
17
+ end
18
+ end
19
+ end
20
+
21
+ def attributes
22
+ self.class.attributes.inject({}) do |attributes, attribute|
23
+ value = send(attribute)
24
+ if !value.nil?
25
+ if value.respond_to?(:attributes)
26
+ attributes["#{attribute}_attributes"] = value.attributes
27
+ else
28
+ unless self.class.nillable_attributes && self.class.nillable_attributes.include?(attribute)
29
+ attributes[attribute] = value
30
+ end
31
+ end
32
+ end; attributes
33
+ end
34
+ end
35
+
36
+ def to_json
37
+ JSON.generate(attributes)
38
+ end
39
+
40
+ def updateable?
41
+ true
42
+ end
43
+
44
+ # Bit of a hack to know whether instances came from the api
45
+ # and know they are persisted
46
+ def from_api=(from_api)
47
+ @from_api = from_api
48
+ end
49
+
50
+ def persisted?
51
+ @from_api == true
52
+ end
53
+
54
+ module ClassMethods
55
+ attr_reader :attributes, :nillable_attributes
56
+
57
+ def has_attributes(attributes)
58
+ attr_accessor(*@attributes = attributes)
59
+ end
60
+
61
+ def has_nillable_attributes(attributes)
62
+ @nillable_attributes = attributes
63
+ end
64
+
65
+ def has_boolean_attributes(attributes)
66
+ attributes.each do |attribute|
67
+ define_method(attribute) do
68
+ input = instance_variable_get('@' + attribute)
69
+ if input.kind_of?(String)
70
+ if input == 'true'
71
+ true
72
+ elsif input == 'false'
73
+ false
74
+ else
75
+ nil
76
+ end
77
+ else
78
+ input
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def has_datetime_attributes(attributes)
85
+ attributes.each do |attribute|
86
+ define_method(attribute) do
87
+ input = instance_variable_get('@' + attribute)
88
+ if input.kind_of?(Time)
89
+ input
90
+ elsif input.kind_of?(Date)
91
+ input.to_time
92
+ elsif input.kind_of?(String)
93
+ input.strip == '' ? nil : Time.parse(input)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,88 @@
1
+ module FsApi
2
+ module Service
3
+ class BaseService
4
+ attr_writer :command_class
5
+ attr_reader :api_client
6
+
7
+ def initialize(api_client)
8
+ @api_client = api_client
9
+ end
10
+
11
+ def resource_type
12
+ self.class.name.split('::').last.downcase
13
+ end
14
+
15
+ def resource_type_plural
16
+ "#{resource_type}s"
17
+ end
18
+
19
+ def path
20
+ "/#{resource_type_plural}"
21
+ end
22
+
23
+ def find(id)
24
+ if response = @api_client.get([path,id].join('/'))
25
+ if response.code.to_i == success_status_code
26
+ json_response = JSON.parse(response.body).merge(from_api: true)
27
+ collection_class.new(json_response[resource_type])
28
+ end
29
+ end
30
+ end
31
+
32
+ def create(attributes)
33
+ instance = build(attributes)
34
+ save(instance)
35
+ instance
36
+ end
37
+
38
+ def build(attributes)
39
+ instance = collection_class.new(attributes)
40
+ instance
41
+ end
42
+
43
+ def delete(instance)
44
+ @api_client.delete(instance.path)
45
+ if api_client._last_response.code.to_i != success_status_code
46
+ instance.errors = api_client._last_response.body
47
+ return false
48
+ end
49
+ end
50
+
51
+ def save(instance)
52
+ return false if instance.persisted? && !instance.updateable?
53
+ if instance.persisted?
54
+ @api_client.put(instance.path, instance.to_json)
55
+ if api_client._last_response.code.to_i != success_status_code
56
+ instance.errors = api_client._last_response
57
+ return false
58
+ end
59
+ else
60
+ @api_client.post(path, instance.to_json)
61
+ if api_client._last_response.code.to_i != create_success_status_code
62
+ instance.errors = api_client._last_response.body
63
+ return false
64
+ end
65
+ end
66
+ true
67
+ end
68
+
69
+ def all
70
+ if response = api_client.get(path)
71
+ if response.code.to_i == success_status_code
72
+ JSON.parse(response.body).map do |attributes|
73
+ collection_class.new(attributes.merge(from_api: true))
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ def create_success_status_code
80
+ 201
81
+ end
82
+
83
+ def success_status_code
84
+ 200
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,9 @@
1
+ module FsApi
2
+ module Service
3
+ class Client < BaseService
4
+ def collection_class
5
+ FsApi::Resource::Client
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module FsApi
2
+ module Service
3
+ class Invoice < BaseService
4
+ def collection_class
5
+ FsApi::Resource::Invoice
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module FsApi
2
+ module Service
3
+ class Product < BaseService
4
+ def collection_class
5
+ FsApi::Resource::Product
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module FsApi
2
+ VERSION = "0.7.0"
3
+ end
data/lib/fs_api.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'json'
2
+
3
+ require "fs_api/client"
4
+ require "fs_api/service/base_service"
5
+ require "fs_api/service/client"
6
+ require "fs_api/service/invoice"
7
+ require "fs_api/service/product"
8
+ require "fs_api/resource/resource"
9
+ require "fs_api/resource/client"
10
+ require "fs_api/resource/invoice"
11
+ require "fs_api/resource/product"
12
+
13
+ module FsApi
14
+ end
@@ -0,0 +1,61 @@
1
+ require "spec_helper"
2
+
3
+ describe FsApi::Client do
4
+
5
+ let(:client) { described_class.new("username","api_token") }
6
+
7
+ it "sets a username" do
8
+ expect(client.username).to eq 'username'
9
+ end
10
+
11
+ it "sets a token" do
12
+ expect(client.password).to eq 'api_token'
13
+ end
14
+
15
+ describe "request handling" do
16
+ let(:url) {"https://username:api_token@www.factuursturen.nl/api/v1/path" }
17
+
18
+ it "can do a post request" do
19
+ stub = stub_request(:post, url)
20
+
21
+ client.post('/path', 'body')
22
+
23
+ expect(stub).to have_been_requested
24
+ end
25
+
26
+ it "can do a get request" do
27
+ stub = stub_request(:get, url)
28
+
29
+ client.get('/path')
30
+
31
+ expect(stub).to have_been_requested
32
+ end
33
+
34
+ it "can do a put request" do
35
+ stub = stub_request(:put, url)
36
+
37
+ client.put('/path', 'body')
38
+
39
+ expect(stub).to have_been_requested
40
+ end
41
+
42
+ it "can do a delete request" do
43
+ stub = stub_request(:delete, url)
44
+
45
+ client.delete('/path')
46
+
47
+ expect(stub).to have_been_requested
48
+ end
49
+
50
+ describe "response" do
51
+ it "stores last response" do
52
+ stub = stub_request(:post, "https://username:api_token@www.factuursturen.nl/api/v1/path").to_return(body: 'somebody')
53
+
54
+ client.post('/path', 'body')
55
+
56
+ expect(client._last_response.body).to eq 'somebody'
57
+ end
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,56 @@
1
+ require "spec_helper"
2
+
3
+ describe FsApi::Service::Client do
4
+
5
+ let(:api_client) { FsApi::Client.new('username', 'api_key') }
6
+ let(:service) { FsApi::Service::Client.new(api_client) }
7
+ let(:client) { FsApi::Resource::Client.new(json_response(:client).merge('from_api' => true)) }
8
+
9
+ describe "retrieval" do
10
+ it "retrieves all clients" do
11
+ stub_request(:get, "https://username:api_key@www.factuursturen.nl/api/v1/clients").to_return(body: [json_response(:client)].to_json )
12
+
13
+ clients = service.all
14
+
15
+ expect(clients.size).to eq 1
16
+ expect(clients.first.clientnr).to eq '1'
17
+ end
18
+
19
+ it "retrieves a client" do
20
+ stub_request(:get, "https://username:api_key@www.factuursturen.nl/api/v1/clients/1").to_return(body: { 'client' => json_response(:client)}.to_json )
21
+
22
+ client = service.find(1)
23
+
24
+ expect(client.clientnr).to eq '1'
25
+ end
26
+ end
27
+
28
+ describe "deletion" do
29
+ it "deletes a client" do
30
+ stub_request(:delete, "https://username:api_key@www.factuursturen.nl/api/v1/clients/1")
31
+
32
+ service.delete(client)
33
+ end
34
+ end
35
+
36
+ describe "creation" do
37
+ it "creates a client" do
38
+ stub_request(:post, "https://username:api_key@www.factuursturen.nl/api/v1/clients").
39
+ with(:body => "{\"clientnr\":2}")
40
+
41
+ client = service.create({'clientnr' => 2})
42
+
43
+ expect(client.clientnr).to eq 2
44
+ end
45
+ end
46
+
47
+ describe "updates" do
48
+ it "updates a client" do
49
+ stub_request(:put, "https://username:api_key@www.factuursturen.nl/api/v1/clients/1")
50
+
51
+ client.company = 'something'
52
+
53
+ service.save(client)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+ describe FsApi::Service::Client do
4
+
5
+ let(:api_client) { FsApi::Client.new('username', 'api_key') }
6
+ let(:service) { FsApi::Service::Invoice.new(api_client) }
7
+ let(:invoice) { FsApi::Resource::Invoice.new(json_response(:invoice).merge('from_api' => true)) }
8
+
9
+ describe "retrieval" do
10
+ it "retrieves all invoices" do
11
+ stub_request(:get, "https://username:api_key@www.factuursturen.nl/api/v1/invoices").to_return(body: [json_response(:invoice)].to_json )
12
+
13
+ invoices = service.all
14
+
15
+ expect(invoices.size).to eq 1
16
+ expect(invoices.first.invoicenr).to eq 'F20150001'
17
+ end
18
+
19
+ it "retrieves a invoice" do
20
+ stub_request(:get, "https://username:api_key@www.factuursturen.nl/api/v1/invoices/20150001").to_return(body: { 'invoice' => json_response(:invoice)}.to_json )
21
+
22
+ invoice = service.find('20150001')
23
+
24
+ expect(invoice.invoicenr).to eq 'F20150001'
25
+ end
26
+ end
27
+
28
+ describe "deletion" do
29
+ it "deletes a invoice" do
30
+ stub_request(:delete, "https://username:api_key@www.factuursturen.nl/api/v1/invoices/20150001")
31
+
32
+ service.delete(invoice)
33
+ end
34
+ end
35
+
36
+ describe "creation" do
37
+ it "creates a invoice" do
38
+ stub_request(:post, "https://username:api_key@www.factuursturen.nl/api/v1/invoices").
39
+ with(:body => "{\"invoicenr\":2}")
40
+
41
+ invoice = service.create({'invoicenr' => 2})
42
+
43
+ expect(invoice.invoicenr).to eq 2
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe FsApi::Service::Client do
4
+ let(:api_client) { FsApi::Client.new('username', 'api_key') }
5
+
6
+ let(:service) { FsApi::Service::Product.new(api_client) }
7
+ let(:product) { FsApi::Resource::Product.new(json_response(:product).merge('from_api' => true)) }
8
+
9
+ describe "retrieval" do
10
+ it "retrieves all products" do
11
+ stub_request(:get, "https://username:api_key@www.factuursturen.nl/api/v1/products").to_return(body: [json_response(:product)].to_json )
12
+
13
+ products = service.all
14
+ expect(products.size).to eq 1
15
+ expect(products.first.code).to eq "product code"
16
+ end
17
+
18
+ it "retrieves a product" do
19
+ stub_request(:get, "https://username:api_key@www.factuursturen.nl/api/v1/products/1").to_return(body: { 'product' => json_response(:product)}.to_json )
20
+
21
+ product = service.find(1)
22
+
23
+ expect(product.code).to eq "product code"
24
+ end
25
+ end
26
+
27
+ describe "deletion" do
28
+ it "deletes a product" do
29
+ stub_request(:delete, "https://username:api_key@www.factuursturen.nl/api/v1/products/1")
30
+
31
+ service.delete(product)
32
+ end
33
+ end
34
+
35
+ describe "creation" do
36
+ it "creates a product" do
37
+ stub_request(:post, "https://username:api_key@www.factuursturen.nl/api/v1/products").
38
+ with(:body => "{\"code\":2}")
39
+
40
+ product = service.create({'code' => 2})
41
+
42
+ expect(product.code).to eq 2
43
+ end
44
+ end
45
+
46
+ describe "updates" do
47
+ it "updates a product" do
48
+ stub_request(:put, "https://username:api_key@www.factuursturen.nl/api/v1/products/1")
49
+
50
+ product.code = 'something'
51
+
52
+ service.save(product)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,8 @@
1
+ require 'webmock/rspec'
2
+ require 'fs_api'
3
+
4
+ require_relative "support/json_response_helper"
5
+
6
+ RSpec.configure do |config|
7
+ config.include JsonResponseHelper
8
+ end
@@ -0,0 +1,13 @@
1
+ module JsonResponseHelper
2
+ def json_filename(name)
3
+ File.join('spec/support/responses/', "#{name}.json")
4
+ end
5
+
6
+ def json_response_raw(name)
7
+ File.read(json_filename(name))
8
+ end
9
+
10
+ def json_response(name)
11
+ JSON.parse(json_response_raw(name)).delete_if { |k, v| v.nil? }
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ {
2
+ "clientnr":"1",
3
+ "contact":"",
4
+ "showcontact":"true",
5
+ "company":"kees",
6
+ "address":"",
7
+ "zipcode":"",
8
+ "city":"ROTT",
9
+ "country":"146",
10
+ "phone":"",
11
+ "mobile":"",
12
+ "email":"",
13
+ "bankcode":"",
14
+ "biccode":"",
15
+ "taxnumber":"",
16
+ "tax_shifted":"false",
17
+ "lastinvoice":"2015-11-24",
18
+ "sendmethod":"mail",
19
+ "paymentmethod":"bank",
20
+ "top":"30",
21
+ "stddiscount":"0",
22
+ "mailintro":"Geachte heer\/mevrouw,",
23
+ "reference":{
24
+ "line1":"",
25
+ "line2":"",
26
+ "line3":""
27
+ },
28
+ "notes":"",
29
+ "notes_on_invoice":"false",
30
+ "active":"true",
31
+ "default_doclang":"",
32
+ "default_email":"0",
33
+ "currency":"EUR",
34
+ "mandate_id":"",
35
+ "mandate_date":"",
36
+ "collecttype":"FRST",
37
+ "tax_type":"extax",
38
+ "default_category":"0"
39
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "id":"20150001",
3
+ "invoicenr_full":"F20150001",
4
+ "invoicenr":"F20150001",
5
+ "reference":{
6
+ "line1":"",
7
+ "line2":"",
8
+ "line3":""
9
+ },
10
+ "lines":{
11
+ "line1":{
12
+ "amount":1,
13
+ "amount_desc":"",
14
+ "description":"test",
15
+ "tax_rate":21,
16
+ "price":0,
17
+ "discount_pct":0,
18
+ "linetotal":0
19
+ }
20
+ },
21
+ "profile":"1",
22
+ "discounttype":"percentage",
23
+ "discount":"0",
24
+ "paymentcondition":"Betalingsconditie: betaling binnen %PAYMENT_PERIOD% dagen o.v.v. het factuur- en klantnummer",
25
+ "paymentperiod":"30",
26
+ "collection":"0",
27
+ "tax":"0.00",
28
+ "totalintax":"0.00",
29
+ "clientnr":"2",
30
+ "company":"",
31
+ "contact":"",
32
+ "address":"",
33
+ "zipcode":"",
34
+ "city":"",
35
+ "country":"146",
36
+ "phone":"",
37
+ "mobile":"",
38
+ "email":"",
39
+ "taxnumber":"",
40
+ "invoicenote":"",
41
+ "sent":"2015-11-24",
42
+ "uncollectible":"",
43
+ "lastreminder":"",
44
+ "open":"0.00",
45
+ "paiddate":"",
46
+ "taxes":{
47
+ "tax1":{
48
+ "rate":21,
49
+ "sum":"0.00",
50
+ "sum_of":"0.00"
51
+ }
52
+ },
53
+ "payment_url":"https:\/\/www.factuursturen.nl\/pay?",
54
+ "duedate":"2015-12-24",
55
+ "history":{
56
+ "item1":{
57
+ "date":"2015-11-24",
58
+ "time":"18:09",
59
+ "description":"Factuur verstuurd"
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "id":"1",
3
+ "code":"product code",
4
+ "name":"Some line",
5
+ "price":"120",
6
+ "taxes":"21",
7
+ "priceintax":"145.2"
8
+ }
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fs_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.0
5
+ platform: ruby
6
+ authors:
7
+ - Maarten van Vliet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: webmock
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.21'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.21'
41
+ description: 'Ruby-Api library for factuursturen.nl. As of yet incomplete support
42
+ for the api, but functional '
43
+ email:
44
+ - maartenvanvliet@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".kick"
51
+ - ".rspec"
52
+ - Gemfile
53
+ - LICENSE.txt
54
+ - README.md
55
+ - fs_api.gemspec
56
+ - lib/fs_api.rb
57
+ - lib/fs_api/client.rb
58
+ - lib/fs_api/resource/client.rb
59
+ - lib/fs_api/resource/invoice.rb
60
+ - lib/fs_api/resource/product.rb
61
+ - lib/fs_api/resource/resource.rb
62
+ - lib/fs_api/service/base_service.rb
63
+ - lib/fs_api/service/client.rb
64
+ - lib/fs_api/service/invoice.rb
65
+ - lib/fs_api/service/product.rb
66
+ - lib/fs_api/version.rb
67
+ - spec/lib/fs_api/client_spec.rb
68
+ - spec/lib/fs_api/service/client_spec.rb
69
+ - spec/lib/fs_api/service/invoice_spec.rb
70
+ - spec/lib/fs_api/service/product_spec.rb
71
+ - spec/spec_helper.rb
72
+ - spec/support/json_response_helper.rb
73
+ - spec/support/responses/client.json
74
+ - spec/support/responses/invoice.json
75
+ - spec/support/responses/product.json
76
+ homepage: ''
77
+ licenses:
78
+ - MIT
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.2.2
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Ruby-Api library for factuursturen.nl
100
+ test_files:
101
+ - spec/lib/fs_api/client_spec.rb
102
+ - spec/lib/fs_api/service/client_spec.rb
103
+ - spec/lib/fs_api/service/invoice_spec.rb
104
+ - spec/lib/fs_api/service/product_spec.rb
105
+ - spec/spec_helper.rb
106
+ - spec/support/json_response_helper.rb
107
+ - spec/support/responses/client.json
108
+ - spec/support/responses/invoice.json
109
+ - spec/support/responses/product.json
110
+ has_rdoc: