kounta_rest 0.0.1
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 +7 -0
- data/.gitignore +19 -0
- data/.gitmodules +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/console.rb +14 -0
- data/kounta.gemspec +32 -0
- data/lib/kounta.rb +76 -0
- data/lib/kounta/address.rb +18 -0
- data/lib/kounta/category.rb +16 -0
- data/lib/kounta/company.rb +51 -0
- data/lib/kounta/customer.rb +35 -0
- data/lib/kounta/errors.rb +7 -0
- data/lib/kounta/line.rb +23 -0
- data/lib/kounta/order.rb +47 -0
- data/lib/kounta/payment.rb +17 -0
- data/lib/kounta/price_list.rb +10 -0
- data/lib/kounta/product.rb +30 -0
- data/lib/kounta/resource.rb +91 -0
- data/lib/kounta/rest/client.rb +65 -0
- data/lib/kounta/site.rb +42 -0
- data/lib/kounta/tax.rb +10 -0
- data/lib/kounta/version.rb +3 -0
- data/spec/helper.rb +28 -0
- data/spec/kounta/address_spec.rb +11 -0
- data/spec/kounta/category_spec.rb +11 -0
- data/spec/kounta/company_spec.rb +24 -0
- data/spec/kounta/customer_spec.rb +15 -0
- data/spec/kounta/kounta_spec.rb +21 -0
- data/spec/kounta/line_spec.rb +14 -0
- data/spec/kounta/order_spec.rb +37 -0
- data/spec/kounta/payment_spec.rb +14 -0
- data/spec/kounta/product_spec.rb +16 -0
- data/spec/kounta/resource_spec.rb +95 -0
- data/spec/kounta/rest/client_spec.rb +38 -0
- data/spec/kounta/site_spec.rb +11 -0
- data/spec/support/endpoints.rb +67 -0
- metadata +236 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
module Kounta
|
2
|
+
|
3
|
+
class Product < Kounta::Resource
|
4
|
+
property :company_id
|
5
|
+
property :code
|
6
|
+
property :barcode
|
7
|
+
property :stock
|
8
|
+
property :name
|
9
|
+
property :description
|
10
|
+
property :tags
|
11
|
+
property :image
|
12
|
+
property :unit_price
|
13
|
+
property :cost_price
|
14
|
+
property :taxes
|
15
|
+
property :sites
|
16
|
+
|
17
|
+
has_many :categories, Kounta::Category, {:company_id => :company_id}, lambda { |klass| {companies: klass.company_id, products: klass.company_id, categories: nil} }
|
18
|
+
coerce_key :taxes, Kounta::Tax
|
19
|
+
|
20
|
+
def tags_include?(name)
|
21
|
+
tags.any?{ |s| s.casecmp(name) == 0 }
|
22
|
+
end
|
23
|
+
|
24
|
+
def resource_path
|
25
|
+
{companies: company_id, products: id}
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
require_relative "rest/client"
|
3
|
+
|
4
|
+
module Kounta
|
5
|
+
|
6
|
+
class Resource < Hashie::Dash
|
7
|
+
include Hashie::Extensions::Coercion
|
8
|
+
|
9
|
+
property :id
|
10
|
+
property :created_at
|
11
|
+
property :updated_at
|
12
|
+
|
13
|
+
def self.coerce(data)
|
14
|
+
if data.kind_of? Array
|
15
|
+
data.map { |item| self.new(item) }
|
16
|
+
else
|
17
|
+
self.new(data)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.has_one(sym, klass, assignments, route)
|
22
|
+
define_method(sym) do |item_id=nil, *args|
|
23
|
+
if item_id
|
24
|
+
assign_into(client.object_from_response(klass, :get, route.call(self, item_id), {:params => args[0]}), self, assignments)
|
25
|
+
else
|
26
|
+
assign_into(klass.new, self, assignments)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.has_many(sym, klass, assignments, route)
|
32
|
+
define_method(sym) do |*args|
|
33
|
+
client.objects_from_response(klass, :get, route.call(self), {:params => args[0]}).map {|returned_klass| assign_into(returned_klass, self, assignments) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(hash={})
|
38
|
+
if hash
|
39
|
+
hash.each_pair do |k,v|
|
40
|
+
begin
|
41
|
+
self[k] = v
|
42
|
+
rescue NoMethodError => e
|
43
|
+
raise Kounta::Errors::UnknownResourceAttribute.new("Unknown attribute: #{k} on resource #{self.class}")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def client
|
50
|
+
@@client ||= Kounta::REST::Client.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_hash(hash={})
|
54
|
+
{}.tap do |returning|
|
55
|
+
self.class.properties.each do |property|
|
56
|
+
next if ignored_properties.include?(property)
|
57
|
+
returning[property] = self[property] if self[property]
|
58
|
+
end
|
59
|
+
end.merge(hash)
|
60
|
+
end
|
61
|
+
|
62
|
+
def save!
|
63
|
+
response = new? ? client.perform(resource_path, :post, {:body => to_hash}) : client.perform(resource_path, :put, {:body => to_hash})
|
64
|
+
if response
|
65
|
+
response.each_pair do |k,v|
|
66
|
+
self[k] = v
|
67
|
+
end
|
68
|
+
end
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def new?
|
73
|
+
!id
|
74
|
+
end
|
75
|
+
|
76
|
+
def ignored_properties(array=[])
|
77
|
+
array + [:created_at, :updated_at, :id, :company_id, :site_id]
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def assign_into(klass, assigner, assignments)
|
83
|
+
assignments.each_pair do |k,v|
|
84
|
+
klass[k] = assigner[v]
|
85
|
+
end
|
86
|
+
klass
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
require 'yell'
|
3
|
+
|
4
|
+
module Kounta
|
5
|
+
module REST
|
6
|
+
class Client
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
raise Kounta::Errors::MissingOauthDetails unless has_required_oauth_details?
|
10
|
+
@logger = Yell.new STDOUT
|
11
|
+
@conn = OAuth2::AccessToken.new(client, Kounta.client_token, {:refresh_token => Kounta.client_refresh_token})
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def client
|
16
|
+
@oauth_client ||= OAuth2::Client.new(Kounta.client_id, Kounta.client_secret, {
|
17
|
+
:site => Kounta::SITE_URI,
|
18
|
+
:authorize_url => Kounta::AUTHORIZATION_URI,
|
19
|
+
:token_url => Kounta::TOKEN_URI
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
def path_from_hash(url_hash)
|
24
|
+
url_hash.map{ |key, value| value ? "#{key}/#{value}" : "#{key}" }.join('/')
|
25
|
+
end
|
26
|
+
|
27
|
+
def perform(url_hash, request_method, options={})
|
28
|
+
begin
|
29
|
+
log("#{request_method}: #{Kounta::SITE_URI}#{path_from_hash(url_hash)}.#{FORMAT.to_s} (#{options})")
|
30
|
+
response = @conn.request(request_method, "#{path_from_hash(url_hash)}.#{FORMAT.to_s}", options)
|
31
|
+
rescue OAuth2::Error => ex
|
32
|
+
if ex.message.include? 'The access token provided has expired'
|
33
|
+
log('oauth2 token expired, refreshing it...')
|
34
|
+
@conn = refreshed_token
|
35
|
+
retry
|
36
|
+
end
|
37
|
+
end
|
38
|
+
response.parsed if response
|
39
|
+
end
|
40
|
+
|
41
|
+
def objects_from_response(klass, request_method, url_hash, options={})
|
42
|
+
perform(url_hash, request_method, options).map { |response| klass.new(response) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def object_from_response(klass, request_method, url_hash, options={})
|
46
|
+
klass.new( perform(url_hash, request_method, options) )
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def has_required_oauth_details?
|
52
|
+
Kounta.client_id && Kounta.client_secret && Kounta.client_token && Kounta.client_refresh_token
|
53
|
+
end
|
54
|
+
|
55
|
+
def log(message)
|
56
|
+
@logger.info(message) unless !Kounta.enable_logging
|
57
|
+
end
|
58
|
+
|
59
|
+
def refreshed_token
|
60
|
+
OAuth2::AccessToken.from_hash(client, :refresh_token => Kounta.client_refresh_token).refresh!
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/kounta/site.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Kounta
|
2
|
+
|
3
|
+
class Site < Kounta::Resource
|
4
|
+
property :company_id
|
5
|
+
property :name
|
6
|
+
property :code
|
7
|
+
property :business_number
|
8
|
+
property :contact_person
|
9
|
+
property :shipping_address
|
10
|
+
property :postal_address
|
11
|
+
property :email
|
12
|
+
property :mobile
|
13
|
+
property :phone
|
14
|
+
property :fax
|
15
|
+
property :location
|
16
|
+
property :image
|
17
|
+
property :website
|
18
|
+
property :register_level_reconciliation
|
19
|
+
property :products
|
20
|
+
property :price_list
|
21
|
+
|
22
|
+
coerce_key :shipping_address, Kounta::Address
|
23
|
+
coerce_key :postal_address, Kounta::Address
|
24
|
+
coerce_key :price_list, Kounta::PriceList
|
25
|
+
|
26
|
+
has_one :product, Kounta::Product, {:company_id => :company_id}, lambda { |klass, item_id| {companies: klass.company_id, sites: klass.id, products: item_id} }
|
27
|
+
has_one :category, Kounta::Category, {:company_id => :company_id}, lambda { |klass, item_id| {companies: klass.company_id, sites: klass.id, categories: item_id} }
|
28
|
+
has_one :address, Kounta::Address, {:company_id => :company_id}, lambda { |klass, item_id| {companies: klass.company_id, sites: klass.id, addresses: item_id} }
|
29
|
+
has_one :order, Kounta::Order, {:company_id => :company_id}, lambda { |klass, item_id| {companies: klass.company_id, sites: klass.id, orders: item_id} }
|
30
|
+
|
31
|
+
has_many :products, Kounta::Product, {:company_id => :company_id}, lambda { |klass| {companies: klass.company_id, sites: klass.id, products: nil} }
|
32
|
+
has_many :categories, Kounta::Category, {:company_id => :company_id}, lambda { |klass| {companies: klass.company_id, sites: klass.id, categories: nil} }
|
33
|
+
has_many :addresses, Kounta::Address, {:company_id => :company_id}, lambda { |klass| {companies: klass.company_id, sites: klass.id, addresses: nil} }
|
34
|
+
has_many :orders, Kounta::Order, {:company_id => :company_id}, lambda { |klass| {companies: klass.company_id, sites: klass.id, orders: nil} }
|
35
|
+
|
36
|
+
def resource_path
|
37
|
+
{companies: company_id, sites: id}
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/kounta/tax.rb
ADDED
data/spec/helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'webmock/rspec'
|
6
|
+
require 'kounta'
|
7
|
+
|
8
|
+
# Requires supporting files with custom matchers and macros, etc,
|
9
|
+
# in ./support/ and its subdirectories.
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
11
|
+
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.include Helpers
|
14
|
+
|
15
|
+
config.before(:each) do
|
16
|
+
|
17
|
+
stub_endpoints
|
18
|
+
|
19
|
+
Kounta.configure do |config|
|
20
|
+
config.client_id = "1234"
|
21
|
+
config.client_secret = "5678"
|
22
|
+
config.client_token = "abcd"
|
23
|
+
config.client_refresh_token = "efgh"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "helper"
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
describe Kounta::Company do
|
5
|
+
|
6
|
+
subject { Kounta::Company }
|
7
|
+
|
8
|
+
it "should be able to create a company from an existing hash" do
|
9
|
+
subject.new(Oj.load(File.read("#{Kounta.root}/spec/fixtures/companies_me.json")))
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be able to create a company without a hash" do
|
13
|
+
subject.new.should be_an_instance_of subject
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have a resource path" do
|
17
|
+
subject.new.resource_path.should eq({companies: 162})
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have a base price list" do
|
21
|
+
subject.new.base_price_list.should be_an_instance_of Kounta::PriceList
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Kounta::Customer do
|
4
|
+
|
5
|
+
subject { Kounta::Company.new.customer(389427) }
|
6
|
+
|
7
|
+
it "should have a name" do
|
8
|
+
subject.name.should eq("Samuel Richardson")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have a resource path" do
|
12
|
+
subject.resource_path.should eq({companies: 162, customers: 389427})
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Kounta do
|
4
|
+
|
5
|
+
subject { Kounta }
|
6
|
+
|
7
|
+
it "should be able to call a configure block" do
|
8
|
+
subject.configure do |config|
|
9
|
+
config.should be(Kounta)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be able to configure loggin" do
|
14
|
+
Kounta.enable_logging.should be(false)
|
15
|
+
Kounta.enable_logging = true
|
16
|
+
Kounta.enable_logging.should be(true)
|
17
|
+
Kounta.enable_logging = false
|
18
|
+
Kounta.enable_logging.should be(false)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Kounta::Line do
|
4
|
+
|
5
|
+
subject { Kounta::Line.new }
|
6
|
+
|
7
|
+
it "should have a resource path" do
|
8
|
+
subject.company_id = 162
|
9
|
+
subject.order_id = 6789
|
10
|
+
subject.id = 1
|
11
|
+
subject.resource_path.should eq({companies: 162, orders: 6789, lines: 1})
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Kounta::Order do
|
4
|
+
|
5
|
+
subject { Kounta::Company.new.customer(701892).order(93824701) }
|
6
|
+
|
7
|
+
it "should be able to add payments to new orders" do
|
8
|
+
new_order = Kounta::Order.new
|
9
|
+
new_order.payments << Kounta::Payment.new(:amount => 50.00)
|
10
|
+
new_order.to_hash[:payments].length.should be(1)
|
11
|
+
new_order.to_hash[:payments][0][:amount].should be(50.00)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be able to add lines to new orders" do
|
15
|
+
new_order = Kounta::Order.new
|
16
|
+
new_order.lines << Kounta::Line.new(:quantity => 4)
|
17
|
+
new_order.to_hash[:lines].length.should be(1)
|
18
|
+
new_order.to_hash[:lines][0][:quantity].should be(4)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be able to add and serialise payments to created orders" do
|
22
|
+
subject.payments << Kounta::Payment.new(:amount => 50.00)
|
23
|
+
subject.to_hash[:payments].length.should be(3)
|
24
|
+
subject.to_hash[:payments][2][:amount].should be(50.00)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be able to add and serialise lines to created orders" do
|
28
|
+
subject.lines << Kounta::Line.new(:quantity => 4)
|
29
|
+
subject.to_hash[:lines].length.should be(3)
|
30
|
+
subject.to_hash[:lines][0][:quantity].should be(6)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have a resource path" do
|
34
|
+
subject.resource_path.should eq({companies: 162, orders: 93824701})
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Kounta::Payment do
|
4
|
+
|
5
|
+
subject { Kounta::Payment.new }
|
6
|
+
|
7
|
+
it "should have a resource path" do
|
8
|
+
subject.company_id = 162
|
9
|
+
subject.order_id = 6789
|
10
|
+
subject.id = 1
|
11
|
+
subject.resource_path.should eq({companies: 162, orders: 6789, payments: 1})
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|