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