fs_api 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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: