fortnox-api 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -17
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +127 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +1 -1
- data/README.md +131 -7
- data/Rakefile +5 -1
- data/fortnox-api.gemspec +13 -3
- data/lib/fortnox/api.rb +11 -1
- data/lib/fortnox/api/base.rb +56 -0
- data/lib/fortnox/api/class_methods.rb +62 -0
- data/lib/fortnox/api/customer.rb +15 -0
- data/lib/fortnox/api/customer/entity.rb +179 -0
- data/lib/fortnox/api/customer/repository.rb +28 -0
- data/lib/fortnox/api/customer/validator.rb +26 -0
- data/lib/fortnox/api/entity.rb +45 -0
- data/lib/fortnox/api/repository/base.rb +27 -0
- data/lib/fortnox/api/repository/json_convertion.rb +55 -0
- data/lib/fortnox/api/repository/loaders.rb +49 -0
- data/lib/fortnox/api/repository/savers.rb +15 -0
- data/lib/fortnox/api/validator.rb +32 -0
- data/lib/fortnox/api/version.rb +1 -1
- data/spec/fortnox/api/base_spec.rb +93 -0
- data/spec/fortnox/api/customer/repository_spec.rb +0 -0
- data/spec/fortnox/api/customer/validator_spec.rb +32 -0
- data/spec/fortnox/api/entity_spec.rb +62 -0
- data/spec/spec_helper.rb +19 -0
- metadata +163 -8
@@ -0,0 +1,62 @@
|
|
1
|
+
module Fortnox
|
2
|
+
module API
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
def get_access_token( base_url: nil, client_secret: nil, authorization_code: nil )
|
6
|
+
base_url = validate_base_url( base_url )
|
7
|
+
client_secret = validate_client_secret( client_secret )
|
8
|
+
authorization_code = validate_authorization_code( authorization_code )
|
9
|
+
|
10
|
+
base_uri( base_url )
|
11
|
+
|
12
|
+
set_headers(
|
13
|
+
'Accept' => 'application/json',
|
14
|
+
'Client-Secret' => client_secret,
|
15
|
+
'Authorisation-Code' => authorization_code,
|
16
|
+
)
|
17
|
+
|
18
|
+
response = get('/')
|
19
|
+
response[ 'Authorisation' ][ 'AccessToken' ]
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_header( name: nil, value: nil )
|
23
|
+
headers[ name ] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_headers( headers = {} )
|
27
|
+
headers.each do |name, value|
|
28
|
+
set_header( name: name, value: value )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def remove_header( name: nil )
|
33
|
+
headers.delete( name )
|
34
|
+
end
|
35
|
+
|
36
|
+
def validate_base_url( base_url )
|
37
|
+
base_url ||= ENV['FORTNOX_API_BASE_URL']
|
38
|
+
fail ArgumentError, 'You have to provide a base url.' unless base_url
|
39
|
+
base_url
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_client_secret( client_secret )
|
43
|
+
client_secret ||= ENV['FORTNOX_API_CLIENT_SECRET']
|
44
|
+
fail ArgumentError, 'You have to provide your client secret.' unless client_secret
|
45
|
+
client_secret
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_access_token( access_token )
|
49
|
+
access_token ||= ENV['FORTNOX_API_ACCESS_TOKEN']
|
50
|
+
fail ArgumentError, 'You have to provide your access token.' unless access_token
|
51
|
+
access_token
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_authorization_code( authorization_code )
|
55
|
+
authorization_code ||= ENV['FORTNOX_API_AUTHORIZATION_CODE']
|
56
|
+
fail ArgumentError, 'You have to provide your access token.' unless authorization_code
|
57
|
+
authorization_code
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "fortnox/api/customer/repository"
|
2
|
+
require "fortnox/api/customer/validator"
|
3
|
+
require "fortnox/api/customer/entity"
|
4
|
+
|
5
|
+
module Fortnox
|
6
|
+
module API
|
7
|
+
module Customer
|
8
|
+
|
9
|
+
def self.new( hash = {} )
|
10
|
+
Entity.new( hash )
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require "fortnox/api/entity"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Customer
|
6
|
+
class Entity < Fortnox::API::Entity
|
7
|
+
|
8
|
+
#Url Direct URL to the record
|
9
|
+
attribute :url, String, writer: :private
|
10
|
+
|
11
|
+
#Address1 First address of the customer
|
12
|
+
attribute :address1, String
|
13
|
+
|
14
|
+
#Address2 Second address of the customer
|
15
|
+
attribute :address2, String
|
16
|
+
|
17
|
+
#City City of the customer
|
18
|
+
attribute :city, String
|
19
|
+
|
20
|
+
#Country Country of the customer
|
21
|
+
attribute :country, String
|
22
|
+
|
23
|
+
#Comments Comments
|
24
|
+
attribute :comments, String
|
25
|
+
|
26
|
+
#Currency Currency of the customer, 3 letters
|
27
|
+
attribute :currency, String
|
28
|
+
|
29
|
+
#CostCenter Cost center of the customer, Cost center in Fortnox
|
30
|
+
attribute :cost_center, String
|
31
|
+
|
32
|
+
#CountryCode Country code of the customer, 2 letters
|
33
|
+
attribute :country_code, String
|
34
|
+
|
35
|
+
#CustomerNumber Customer number
|
36
|
+
attribute :customer_number, String
|
37
|
+
|
38
|
+
#DeliveryAddress1 First delivery address of the customer
|
39
|
+
attribute :delivery_address1, String
|
40
|
+
|
41
|
+
#DeliveryAddress2 Second delivery address of the customer
|
42
|
+
attribute :delivery_address2, String
|
43
|
+
|
44
|
+
#DeliveryCity Delivery city of the customer
|
45
|
+
attribute :delivery_city, String
|
46
|
+
|
47
|
+
#DeliveryCountry Delivery country of the customer
|
48
|
+
attribute :delivery_country, String
|
49
|
+
|
50
|
+
#DeliveryCountryCode Delivery country code of the customer
|
51
|
+
attribute :delivery_country_code, String
|
52
|
+
|
53
|
+
#DeliveryFax Delivery fax number of the customer
|
54
|
+
attribute :delivery_fax, String
|
55
|
+
|
56
|
+
#DeliveryName Delivery name of the customer
|
57
|
+
attribute :delivery_name, String
|
58
|
+
|
59
|
+
#DeliveryPhone1 First delivery phone number of the customer
|
60
|
+
attribute :delivery_phone1, String
|
61
|
+
|
62
|
+
#DeliveryPhone2 Second delivery phone number of the customer
|
63
|
+
attribute :delivery_phone2, String
|
64
|
+
|
65
|
+
#DeliveryZipCode Delivery zip code of the customer
|
66
|
+
attribute :delivery_zip_code, String
|
67
|
+
|
68
|
+
#Email Email address of the customer
|
69
|
+
attribute :email, String
|
70
|
+
|
71
|
+
#EmailInvoice Invoice email address of the customer
|
72
|
+
attribute :email_invoice, String
|
73
|
+
|
74
|
+
#EmailInvoiceBCC Invoice BCC email address of the customer
|
75
|
+
attribute :email_invoice_bcc, String
|
76
|
+
|
77
|
+
#EmailInvoiceCC Invoice CC email address of the customer
|
78
|
+
attribute :email_invoice_cc, String
|
79
|
+
|
80
|
+
#EmailOffer Offer email address of the customer
|
81
|
+
attribute :email_offer, String
|
82
|
+
|
83
|
+
#EmailOfferBCC Offer BCC email address of the customer
|
84
|
+
attribute :email_offer_bcc, String
|
85
|
+
|
86
|
+
#EmailOfferCC Offer CC email address of the customer
|
87
|
+
attribute :email_offer_cc, String
|
88
|
+
|
89
|
+
#EmailOrder Order email address of the customer
|
90
|
+
attribute :email_order, String
|
91
|
+
|
92
|
+
#EmailOrderBCC Order BCC email address of the customer
|
93
|
+
attribute :email_order_bcc, String
|
94
|
+
|
95
|
+
#EmailOrderCC Order CC email address of the customer
|
96
|
+
attribute :email_order_cc, String
|
97
|
+
|
98
|
+
#Fax Fax number of the customer
|
99
|
+
attribute :fax, String
|
100
|
+
|
101
|
+
#InvoiceAdministrationFee Invoice administration fee of the customer
|
102
|
+
attribute :invoice_administration_fee, Float
|
103
|
+
|
104
|
+
#InvoiceDiscount Invoice discount of the customer
|
105
|
+
attribute :invoice_discount, Float
|
106
|
+
|
107
|
+
#InvoiceFreight Invoice freight fee of the customer
|
108
|
+
attribute :invoice_freight, Float
|
109
|
+
|
110
|
+
#InvoiceRemark Invoice remark of the customer
|
111
|
+
attribute :invoice_remark, String
|
112
|
+
|
113
|
+
#Name Name of the customer
|
114
|
+
attribute :name, String
|
115
|
+
|
116
|
+
#OrganisationNumber Organisation number of the customer
|
117
|
+
attribute :organisation_number, String
|
118
|
+
|
119
|
+
#OurReference Our reference of the customer
|
120
|
+
attribute :our_reference, String
|
121
|
+
|
122
|
+
#Phone1 First phone number of the customer
|
123
|
+
attribute :phone1, String
|
124
|
+
|
125
|
+
#Phone2 Second phone number of the customer
|
126
|
+
attribute :phone2, String
|
127
|
+
|
128
|
+
#PriceList Price list of the customer, Price list in Fortnox
|
129
|
+
attribute :price_list, String
|
130
|
+
|
131
|
+
#Project Project of the customer, Project in Fortnox
|
132
|
+
attribute :project, Integer
|
133
|
+
|
134
|
+
#SalesAccount Sales account of the customer, 4 digits
|
135
|
+
attribute :sales_account, Integer
|
136
|
+
|
137
|
+
#ShowPriceVATIncluded Show prices with VAT included or not
|
138
|
+
attribute :show_price_vat_included, Boolean
|
139
|
+
|
140
|
+
#TermsOfDeliveryCode Terms of delivery code of the customer
|
141
|
+
attribute :terms_of_delivery_code, String
|
142
|
+
|
143
|
+
#TermsOfPaymentCode Terms of payment code of the customer
|
144
|
+
attribute :terms_of_payment_code, String
|
145
|
+
|
146
|
+
#Type Customer type, PRIVATE / COMPANY
|
147
|
+
attribute :type, String
|
148
|
+
|
149
|
+
#VATNumber VAT number of the customer
|
150
|
+
attribute :vat_number, String
|
151
|
+
|
152
|
+
#VATType VAT type of the customer, SEVAT / SEREVERSEDVAT / EUREVERSEDVAT / EUVAT / EXPORT
|
153
|
+
attribute :vat_type, String
|
154
|
+
|
155
|
+
#VisitAddress Visit address of the customer
|
156
|
+
attribute :visit_address, String
|
157
|
+
|
158
|
+
#VisitCity Visit city of the customer
|
159
|
+
attribute :visit_city, String
|
160
|
+
|
161
|
+
#VisitCountry Visit country of the customer
|
162
|
+
attribute :visit_country, String
|
163
|
+
|
164
|
+
#VisitZipCode Visit zip code of the customer
|
165
|
+
attribute :visit_zip_code, String
|
166
|
+
|
167
|
+
#WayOfDeliveryCode Way of delivery code of the customer
|
168
|
+
attribute :way_of_delivery_code, String
|
169
|
+
|
170
|
+
#YourReference Your reference of the customer
|
171
|
+
attribute :your_reference, String
|
172
|
+
|
173
|
+
#ZipCode Zip code of the customer
|
174
|
+
attribute :zip_code, String
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "fortnox/api/repository/base"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Customer
|
6
|
+
class Repository < Fortnox::API::Repository::Base
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(
|
10
|
+
base_uri: '/customers/',
|
11
|
+
json_list_wrapper: 'Customers',
|
12
|
+
json_unit_wrapper: 'Customer',
|
13
|
+
key_map: {
|
14
|
+
vat_type: "VATType",
|
15
|
+
}
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def instansiate( hash )
|
22
|
+
Fortnox::API::Customer::Entity.new( hash )
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "fortnox/api/validator"
|
2
|
+
|
3
|
+
module Fortnox
|
4
|
+
module API
|
5
|
+
module Customer
|
6
|
+
class Validator
|
7
|
+
|
8
|
+
extend Fortnox::API::Validator
|
9
|
+
|
10
|
+
using_validations do
|
11
|
+
|
12
|
+
validates_presence_of :name
|
13
|
+
|
14
|
+
validates_length_of :currency, length: 3, if: :currency
|
15
|
+
validates_length_of :country_code, length: 2, if: :country_code
|
16
|
+
|
17
|
+
validates_inclusion_of :sales_account, within: (0..9999), if: :sales_account
|
18
|
+
validates_inclusion_of :type, within: ['PRIVATE', 'COMPANY'], if: :type
|
19
|
+
validates_inclusion_of :vat_type, within: ['SEVAT', 'SEREVERSEDVAT', 'EUREVERSEDVAT', 'EUVAT', 'EXPORT'], if: :vat_type
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "virtus"
|
2
|
+
require "ice_nine"
|
3
|
+
|
4
|
+
module Fortnox
|
5
|
+
module API
|
6
|
+
class Entity
|
7
|
+
|
8
|
+
extend Forwardable
|
9
|
+
include Virtus.model
|
10
|
+
|
11
|
+
attr_accessor :unsaved
|
12
|
+
|
13
|
+
def initialize( hash = {} )
|
14
|
+
@unsaved = hash.delete( :unsaved ){ true }
|
15
|
+
super
|
16
|
+
IceNine.deep_freeze( self )
|
17
|
+
end
|
18
|
+
|
19
|
+
def update( hash )
|
20
|
+
attributes = self.to_hash.merge( hash )
|
21
|
+
|
22
|
+
return self if attributes == self.to_hash
|
23
|
+
|
24
|
+
self.class.new( attributes )
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generic comparison, by value, use .eql? or .equal? for object identity.
|
28
|
+
def ==( other )
|
29
|
+
return false unless other.is_a? self.class
|
30
|
+
self.to_hash == other.to_hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_json
|
34
|
+
hash = attribute_set.each_with_object({}) do |attribute, hash|
|
35
|
+
name = attribute.options[ :name ]
|
36
|
+
key = attribute.options[ :json_name ] || attribute_name_to_json( name )
|
37
|
+
value = attributes[name]
|
38
|
+
hash[ key ] = value
|
39
|
+
end
|
40
|
+
hash.to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "fortnox/api/base"
|
2
|
+
require "fortnox/api/repository/json_convertion"
|
3
|
+
require "fortnox/api/repository/loaders"
|
4
|
+
require "fortnox/api/repository/savers"
|
5
|
+
|
6
|
+
module Fortnox
|
7
|
+
module API
|
8
|
+
module Repository
|
9
|
+
class Base < Fortnox::API::Base
|
10
|
+
|
11
|
+
include JSONConvertion
|
12
|
+
include Loaders
|
13
|
+
include Savers
|
14
|
+
|
15
|
+
def initialize( options = {} )
|
16
|
+
super()
|
17
|
+
@base_uri = options.fetch( :base_uri ){ '/' }
|
18
|
+
@json_list_wrapper = options.fetch( :json_list_wrapper ){ '' }
|
19
|
+
@json_unit_wrapper = options.fetch( :json_unit_wrapper ){ '' }
|
20
|
+
@attr_to_json_map = options.fetch( :key_map ){ {} }
|
21
|
+
@json_to_attr_map = @attr_to_json_map.invert
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fortnox
|
2
|
+
module API
|
3
|
+
module Repository
|
4
|
+
module JSONConvertion
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def hash_to_entity( entity_json_hash )
|
9
|
+
entity_hash = convert_hash_keys_from_json_format( entity_json_hash )
|
10
|
+
instansiate( entity_hash )
|
11
|
+
end
|
12
|
+
|
13
|
+
def entity_to_hash( entity )
|
14
|
+
entity_hash = entity.to_hash
|
15
|
+
entity_json_hash = convert_hash_keys_to_json_format( entity_hash )
|
16
|
+
{ @json_unit_wrapper => entity_json_hash }
|
17
|
+
end
|
18
|
+
|
19
|
+
def convert_hash_keys_from_json_format( hash )
|
20
|
+
hash.each_with_object( {} ) do |(key, value), json_hash|
|
21
|
+
json_hash[ convert_key_from_json( key ) ] = value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def convert_key_from_json( key )
|
26
|
+
@json_to_attr_map.fetch( key ){ default_key_from_json_transform( key ) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_key_from_json_transform( key )
|
30
|
+
key = key.to_s
|
31
|
+
return key.downcase if key.match(/\A[A-Z]+\z/)
|
32
|
+
key.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
33
|
+
gsub(/([a-z])([A-Z])/, '\1_\2').
|
34
|
+
downcase.
|
35
|
+
to_sym
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_hash_keys_to_json_format( hash )
|
39
|
+
hash.each_with_object( {} ) do |key, value, json_hash|
|
40
|
+
json_hash[ convert_key_to_json( key ) ] = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def convert_key_to_json( key )
|
45
|
+
@attr_to_json_map.fetch( key ){ default_key_to_json_transform( key ) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def default_key_to_json_transform( key )
|
49
|
+
key.to_s.split('_').map(&:capitalize).join('')
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|