sk_sdk 0.2.2 → 0.3.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.
data/.gitignore CHANGED
@@ -1,10 +1,9 @@
1
- coverage/*
1
+ coverage/
2
2
  rdoc/*
3
3
  doc/*
4
4
  .yardoc/*
5
5
  pkg/*
6
- ci/Gemfile.lock
7
- ci/Gemfile_ar2
6
+ ci/Gemfile_ar2.lock
8
7
  ci/vendor
9
8
  ci/.bundle
10
9
  spec/settings.yml
data/README.rdoc CHANGED
@@ -12,7 +12,7 @@ SalesKing App's(using oAuth2) and API clients.
12
12
  Dependencies (gem's):
13
13
 
14
14
  * activesupport
15
- * activeresource v2.3.x, v3.1 (v3.0.10 until sk_sdk v0.0.8)
15
+ * activeresource v2.3.x, v3.1+ (v3.0.10 until sk_sdk v0.0.8)
16
16
  * curb
17
17
  * sk_api_schema
18
18
 
data/ci/Gemfile_ar2 ADDED
@@ -0,0 +1,11 @@
1
+ source :gemcutter
2
+ gem "rake"
3
+ gem "rdoc"
4
+ gem "activesupport", "2.3.14"
5
+ gem "activeresource", "2.3.14"
6
+ gem "sk_api_schema"
7
+ gem "curb"
8
+ group :test do
9
+ gem "rspec"
10
+ gem "simplecov"
11
+ end
@@ -64,28 +64,28 @@ remember we only support HTTPS:
64
64
  =>
65
65
  https://my_company.salesking.eu/api
66
66
 
67
- For convenience we check if your url ends in /api and add if you forgot it!
67
+ For convenience we check if your url ends in /api and add it if you forgot it!
68
68
 
69
69
  Create a single class
70
70
 
71
71
  require 'sk_sdk/base'
72
72
 
73
- class Client < SK::SDK::Base;end
73
+ class Contact < SK::SDK::Base;end
74
74
 
75
75
  # connection using BasicAuth
76
- Client.set_connection( {:site => 'https://my_sub.salesking.eu/api',
76
+ Contact.set_connection( {:site => 'https://my_sub.salesking.eu/api',
77
77
  :user => 'my-users@login-email.com',
78
78
  :password => 'password' })
79
79
 
80
- client = Client.new(:last_name => 'Ding', :organisation => "Carpenters Inc.")
81
- client.first_name = "Bill"
82
- client.save
80
+ contact = Contact.new(:last_name => 'Ding', :organisation => "Carpenters Inc.", :type=>'Client')
81
+ contact.first_name = "Bill"
82
+ contact.save
83
83
 
84
84
  Create multiple classes at once
85
85
 
86
86
  require 'sk_sdk/base'
87
87
  module; King; end
88
- %w[Client Invoice Product LineItem].each do |model|
88
+ %w[Contact Invoice Product LineItem SubTotalItem].each do |model|
89
89
  eval "class King::#{model} < SK::SDK::Base;end"
90
90
  end
91
91
 
@@ -105,14 +105,14 @@ Create multiple classes at once
105
105
 
106
106
  == Quick start - Basic's
107
107
 
108
- To give it quick shot, point your browser to my-account.salesking.eu/api/clients.json
108
+ To give it quick shot, point your browser to my-account.salesking.eu/api/contacts.json
109
109
  (while beeing logged in) and you will see the JSON in the response.
110
110
  This is an example of a GET-request issued by your browser.
111
111
 
112
112
  Or use CURL, if you prefer the command line:
113
113
 
114
114
  curl -u your@login-mail.com:password \
115
- https://demo.salesking.eu/clients
115
+ https://demo.salesking.eu/api/contacts
116
116
 
117
117
  Request Method overview:
118
118
  GET => read
@@ -130,12 +130,12 @@ A list of resources:
130
130
  GET xy.salesking.eu/api/invoices
131
131
 
132
132
  A single resource
133
- GET xy.salesking.eu/invoices/:id
133
+ GET xy.salesking.eu/api/invoices/:id
134
134
 
135
135
  Returned JSON data for a listings, abbreviated:
136
136
  {
137
- "clients": [ # array of resources => clients
138
- { "client": { # a single resource
137
+ "contacts": [ # array of resources => contacts
138
+ { "contact": { # a single resource
139
139
  "number": "0800013", ..
140
140
  "links":{} #links for the resource
141
141
  }, ...
@@ -147,9 +147,9 @@ Returned JSON data for a listings, abbreviated:
147
147
  "per_page": 30
148
148
  },
149
149
  "links": { # links for the collection
150
- "prev": "/api/clients?page=0",
151
- "next": "/api/clients?page=2",
152
- "self": "/api/clients?page=1"
150
+ "prev": "/api/contacts?page=0",
151
+ "next": "/api/contacts?page=2",
152
+ "self": "/api/contacts?page=1"
153
153
  },
154
154
  }
155
155
 
@@ -167,15 +167,15 @@ Available filters are defined in each json-schema's instances link ({see invoice
167
167
  # q-wildcard search in several fields
168
168
  GET xy.salesking.eu/api/invoices?filter[q]=0815&per_page=40
169
169
 
170
- # find all documents for one or more client
171
- GET xy.salesking.eu/api/documents?filter[client_ids]=:id,:id
170
+ # find all documents for one or more contacts
171
+ GET xy.salesking.eu/api/documents?filter[contact_ids]=:id,:id
172
172
 
173
173
  === POST / Create
174
174
 
175
175
  To create a resource make a POST request containing the json for a single resource.
176
176
 
177
177
  Header: content-type application/json
178
- POST https://my-sub.salesking.eu/invoices.json
178
+ POST https://my-sub.salesking.eu/api/invoices.json
179
179
 
180
180
  {"invoice": {
181
181
  "title": "Your service subscription 2011",
@@ -194,12 +194,13 @@ To create a resource make a POST request containing the json for a single resour
194
194
  === PUT / Update
195
195
 
196
196
  Header: content-type application/json
197
- PUT /api/clients/:id
197
+ PUT /api/contacts/:id
198
198
  {
199
- 'client':
199
+ 'contact':
200
200
  {
201
201
  'gender':'male',
202
- 'first_name': "Andrew"
202
+ 'first_name': "Andrew",
203
+ 'type': 'Client'
203
204
  }
204
205
  }
205
206
 
@@ -207,10 +208,11 @@ To create a resource make a POST request containing the json for a single resour
207
208
 
208
209
  A DELETE request to a resource url deletes and returns the deleted object:
209
210
 
210
- DELETE https://demo.salesking.eu/clients/:id
211
+ DELETE https://demo.salesking.eu/api/contacts/:id
211
212
 
212
213
  == Hints on ActiveResource
213
214
 
215
+ * It sucks!
214
216
  * Most of the magic is coming from ActiveResource so you should read {its README and code}[https://github.com/rails/rails/tree/master/activeresource]
215
217
  * This client does NOT rely on parsing the JSON Schema, since ActiveResource(AR) creates the Getter/Setter methods.
216
218
  * We added some patches for AR to fix JSON parsing issues, due to our nesting.
@@ -226,7 +228,7 @@ command-line http client) for testing. And of course any http library supporting
226
228
  http-basic-auth.
227
229
 
228
230
  * {Getting started tutorial}[http://dev.blog.salesking.eu/api/]
229
- * {SalesKing API Schema}[https://github.com/salesking/sk_api_schema]
231
+ * {SalesKing API Browser}[http://sk-api-browser.herokuapp.com/] - {SalesKing API Schema}[https://github.com/salesking/sk_api_schema]
230
232
  * {Chrome cRest extension}[https://chrome.google.com/extensions/detail/baedhhmoaooldchehjhlpppaieoglhml]
231
233
  * {Poster FF-Plugin - make HTTP request}[https://addons.mozilla.org/en-US/firefox/addon/2691/] (you must be logged into SalesKing)
232
234
  * {JSONView FF-Plugin - view json in firefox}[https://addons.mozilla.org/de/firefox/addon/10869/]
@@ -20,10 +20,16 @@ module ActiveResource
20
20
  end
21
21
  end
22
22
 
23
- # override ARes method to parse only the client part
23
+ # override ARes method to parse only the object part
24
24
  def load_attributes_from_response(response)
25
25
  if response['Content-Length'] != "0" && response.body.strip.size > 0
26
26
  load( self.class.format.decode(response.body)[self.class.element_name] )
27
+ if self.respond_to?(:items)
28
+ # move double nested items up
29
+ new_items = []
30
+ self.items.each { |item| new_items << item.attributes.first[1] }
31
+ self.items = new_items
32
+ end
27
33
  end
28
34
  end
29
35
 
@@ -1,6 +1,6 @@
1
1
  module ActiveResource
2
2
  # Overridden methods to suit SalesKing's nested json format
3
- # only valid for AR 3.1
3
+ # only valid for AR 3.1+
4
4
  # In the future might add a custom format class, see base.format
5
5
  class Base
6
6
 
@@ -8,6 +8,12 @@ module ActiveResource
8
8
  def load_attributes_from_response(response)
9
9
  if (response['Transfer-Encoding'] == 'chunked' || (!response['Content-Length'].blank? && response['Content-Length'] != "0")) && !response.body.nil? && response.body.strip.size > 0
10
10
  load( self.class.format.decode(response.body)[self.class.element_name] )
11
+ #fix double nested items .. active resource SUCKS soooo bad
12
+ if self.respond_to?(:items)
13
+ new_items = []
14
+ self.items.each { |item| new_items << item.attributes.first[1] }
15
+ self.items = new_items
16
+ end
11
17
  @persisted = true
12
18
  end
13
19
  end
@@ -1,5 +1,5 @@
1
1
  module SK
2
2
  module SDK
3
- VERSION = '0.2.2'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
  # create all classes and set their connection
3
- %w[Client Address CreditNote Invoice Product LineItem User].each do |model|
3
+ %w[Contact Address CreditNote Invoice Product LineItem User Payment Email].each do |model|
4
4
  eval "class #{model} < SK::SDK::Base;end" unless Object.const_defined?(model)
5
5
  end
6
6
  SK::SDK::Base.set_connection basic_auth_settings
@@ -8,7 +8,7 @@ SK::SDK::Base.set_connection basic_auth_settings
8
8
  def sk_available?
9
9
  begin
10
10
  User.get(:current)
11
- rescue Errno::ECONNREFUSED #ActiveResource::ResourceNotFound => e
11
+ rescue
12
12
  return false
13
13
  end
14
14
  end
@@ -23,13 +23,10 @@ def kick_existing(obj, number)
23
23
  end
24
24
 
25
25
  def delete_test_data(doc, client)
26
- doc.destroy
26
+ if doc.status !='draft'
27
+ doc.status ='draft'
28
+ doc.save
29
+ end
27
30
  client.destroy
28
- lambda {
29
- doc = Invoice.find(doc.id)
30
- }.should raise_error(ActiveResource::ResourceNotFound)
31
- lambda {
32
- client = Client.find(client.id)
33
- }.should raise_error(ActiveResource::ResourceNotFound)
34
31
  end
35
32
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'resources_spec_helper'
3
3
 
4
- class Client < SK::SDK::Base;end
4
+ class Contact < SK::SDK::Base;end
5
5
  # create objects in King namespace
6
6
  module KingTester; end
7
7
  %w[Invoice Product].each do |model|
@@ -11,7 +11,7 @@ end
11
11
  describe SK::SDK::Base, "make new class" do
12
12
 
13
13
  it "should create class" do
14
- c = Client.new
14
+ c = Contact.new
15
15
  c.first_name = 'herbert' # implicit setter
16
16
  c.first_name.should == 'herbert' # implicit getter
17
17
  end
@@ -25,17 +25,17 @@ describe SK::SDK::Base, "make new class" do
25
25
  end
26
26
 
27
27
  it "should have properties as attributes" do
28
- c = Client.new :some_field => ''
28
+ c = Contact.new :some_field => ''
29
29
  c.attributes.should == {"some_field"=>""}
30
30
  end
31
31
 
32
32
  it "should create save method" do
33
- c = Client.new
33
+ c = Contact.new
34
34
  c.respond_to?(:save).should be_true
35
35
  end
36
36
 
37
37
  it "should have new_record?" do
38
- c = Client.new
38
+ c = Contact.new
39
39
  c.new_record?.should be_true
40
40
  i = KingTester::Invoice.new
41
41
  i.new_record?.should be_true
@@ -46,9 +46,9 @@ describe SK::SDK::Base, "make new class" do
46
46
  it "should allow multiple parameters in initializer" do
47
47
  expect {
48
48
  if ActiveResource::VERSION::MAJOR == 3 && ActiveResource::VERSION::MINOR > 0
49
- Client.new({ :first_name => 'herbert' }, true)
49
+ Contact.new({ :first_name => 'herbert' }, true)
50
50
  else
51
- Client.new({ :first_name => 'herbert' })
51
+ Contact.new({ :first_name => 'herbert' })
52
52
  end
53
53
  }.should_not raise_error(ArgumentError)
54
54
  end
@@ -0,0 +1,100 @@
1
+ require 'resources_spec_helper'
2
+
3
+ unless sk_available?
4
+ puts "Sorry cannot connect to your SalesKing server, skipping real connections tests. Please check connection settings in spec_helper"
5
+ else
6
+
7
+ describe Contact, "with real connection" do
8
+
9
+ before :all do
10
+ @contact = Contact.new(:organisation=>'from testing API2', :type => 'Lead')
11
+ @contact.save
12
+ end
13
+
14
+ after :all do
15
+ #delete test contact
16
+ @contact.destroy
17
+ lambda {
18
+ contact = Contact.find(@contact.id)
19
+ }.should raise_error(ActiveResource::ResourceNotFound)
20
+ end
21
+
22
+ it "should save" do
23
+ c = Contact.new :organisation=>"Rack'n Roll", :type => 'Client'
24
+ c.save.should be_true
25
+ c.id.should_not be_empty
26
+ c.number.should_not be_empty
27
+ c.destroy
28
+ end
29
+
30
+ it "should fail create a contact" do
31
+ contact = Contact.new(:organisation=>'from testing API2', :type => 'Client')
32
+ contact.bank_iban = 'safasf'
33
+ contact.save.should == false
34
+ contact.errors.count.should == 1
35
+ contact.errors.full_messages.should == ["Bank iban is invalid"]
36
+ end
37
+
38
+ it "should find a single contact" do
39
+ contact = Contact.find(@contact.id)
40
+ contact.organisation.should == @contact.organisation
41
+ end
42
+
43
+ it "should find contacts" do
44
+ contacts = Contact.find(:all)
45
+ contacts.should_not be_empty
46
+ end
47
+ end
48
+
49
+
50
+ describe Contact, "with addresses" do
51
+
52
+ before :all do
53
+ #setup test contact to work with
54
+ @contact = Contact.new(:organisation=>'Second from testing API2',
55
+ :type => 'Client',
56
+ :addresses => [{ :zip => '50374', :city => 'Cologne' }] )
57
+
58
+ @contact.save
59
+ end
60
+
61
+ after :all do
62
+ @contact.destroy
63
+ lambda {
64
+ contact = Contact.find(@contact.id)
65
+ }.should raise_error(ActiveResource::ResourceNotFound)
66
+ end
67
+
68
+ it "should create an address" do
69
+ @contact.addresses.length.should == 1
70
+ @contact.addresses.first.zip.should == '50374'
71
+ end
72
+
73
+ it "should edit an address" do
74
+ @contact.addresses.length.should == 1
75
+ # puts @contact.addresses.inspect
76
+ @contact.addresses[0].zip = '40001'
77
+ @contact.save
78
+ @contact.addresses.length.should == 1
79
+ @contact.addresses.first.zip.should == '40001'
80
+ end
81
+
82
+ it "should add an address" do
83
+ cnt_before = @contact.addresses.length
84
+ adr = Address.new( { :zip => '37700', :city => 'Cologne' } )
85
+ @contact.addresses << adr
86
+ @contact.save
87
+ @contact.addresses.length.should == cnt_before+1
88
+ end
89
+
90
+ it "should destroy an address" do
91
+ cnt_before = @contact.addresses.length
92
+ @contact.addresses.last._destroy = 1
93
+ @contact.save
94
+ @contact.reload
95
+ @contact.addresses.length.should == cnt_before-1
96
+ end
97
+ end
98
+
99
+
100
+ end
@@ -8,25 +8,16 @@ else
8
8
 
9
9
  before :all do
10
10
  #setup test doc to work with
11
- # create client
12
- @client = Client.new(:organisation=>'Credit Note API-Tester')
13
- @client.save.should be_true
11
+ @contact = Contact.new(:type=>'Supplier', :organisation=>'Credit Note API-Tester')
12
+ @contact.save.should be_true
14
13
  @doc = CreditNote.new()
15
14
  @doc.title = 'A Document from the API'
16
- @doc.client_id = @client.id
15
+ @doc.contact_id = @contact.id
17
16
  @doc.save.should be_true
18
17
  end
19
18
 
20
19
  after :all do
21
- #delete test doc
22
- @doc.destroy
23
- @client.destroy
24
- lambda {
25
- doc = CreditNote.find(@doc.id)
26
- }.should raise_error(ActiveResource::ResourceNotFound)
27
- lambda {
28
- client = Client.find(@client.id)
29
- }.should raise_error(ActiveResource::ResourceNotFound)
20
+ delete_test_data @doc, @contact
30
21
  end
31
22
 
32
23
  it "should create a doc and use default before after text" do
@@ -41,7 +32,7 @@ else
41
32
  doc.save.should == true
42
33
  doc2 = CreditNote.new(:number=>'001')
43
34
  doc2.save.should == false
44
- doc2.errors.count.should == 2
35
+ doc2.errors.count.should == 1
45
36
  if doc2.errors.respond_to? :on # TODO kick with AR 2.3
46
37
  doc2.errors.on(:number).should == "has already been taken"
47
38
  else
@@ -71,7 +62,7 @@ else
71
62
  doc1.save.should == true
72
63
  @doc.number = '002'
73
64
  @doc.save.should == false
74
- @doc.errors.count.should == 2
65
+ @doc.errors.count.should == 1
75
66
  if @doc.errors.respond_to? :on # TODO kick with AR 2.3
76
67
  @doc.errors.on(:number).should == "has already been taken"
77
68
  else
@@ -84,27 +75,23 @@ else
84
75
  describe CreditNote, "with line items" do
85
76
 
86
77
  before :all do
87
- @client = Client.new(:organisation=>'Credit Note API-Tester')
88
- @client.save.should be_true
78
+ @contact =Contact.new(:type=>'Supplier', :organisation=>'Credit Note API-Tester')
79
+ @contact.save.should be_true
89
80
  #setup test doc to work with
90
- @doc = CreditNote.new :client_id => @client.id,
81
+ @doc = CreditNote.new :contact_id => @contact.id,
91
82
  :line_items =>[{ :position=>1, :description => 'Pork Chops',
92
83
  :quantity => 12, :price_single =>'10.00'}]
93
84
  @doc.save.should be_true
94
85
  end
95
86
 
96
87
  after :all do
97
- @client.destroy #also destroys all docs
98
- # @doc.destroy
99
- lambda {
100
- doc = CreditNote.find(@doc.id)
101
- }.should raise_error(ActiveResource::ResourceNotFound)
88
+ delete_test_data @doc, @contact
102
89
  end
103
90
 
104
91
  it "should create a line item" do
105
92
  @doc.line_items.length.should == 1
106
93
  @doc.line_items.first.description.should == 'Pork Chops'
107
- @doc.price_total.should == 120.0
94
+ @doc.gross_total.should == 120.0
108
95
  end
109
96
 
110
97
  it "should edit line item" do
@@ -120,7 +107,7 @@ else
120
107
  @doc.line_items << item
121
108
  @doc.save
122
109
  @doc.line_items.length.should == 2
123
- @doc.price_total.should == 220.0
110
+ @doc.gross_total.should == 220.0
124
111
  # @doc.line_items[0].zip = '40001'
125
112
  # @doc.line_items.[1].zip.should == '40001'
126
113
  end
@@ -1,169 +1,245 @@
1
- #require 'spec_helper'
2
1
  require 'resources_spec_helper'
3
2
 
4
3
  unless sk_available?
5
- puts "Sorry cannot connect to your SalesKing server, skipping real connections tests. Please check connection settings in spec_helper"
4
+ puts 'Sorry cannot connect to your SalesKing server, skipping real connections tests. Please check connection settings in spec_helper'
6
5
  else
7
6
 
8
- describe Invoice, "in general" do
7
+ describe Invoice do
9
8
 
10
- before :all do
11
- @client = Client.new(:organisation=>'Invoice API-Tester')
12
- @client.save.should be_true
13
- @doc = Invoice.new()
14
- @doc.title = 'A Document from the API'
15
- @doc.client_id = @client.id
16
- @doc.save.should be_true
17
- end
9
+ context 'in general' do
18
10
 
19
- after :all do
20
- delete_test_data(@doc, @client)
21
- end
11
+ before :all do
12
+ @contact = Contact.new(:type=>'Client', :organisation=>'Invoice API-Tester')
13
+ @contact.save.should be_true
14
+ @doc = Invoice.new()
15
+ @doc.title = 'A Document from the API'
16
+ @doc.contact_id = @contact.id
17
+ @doc.save.should be_true
18
+ end
22
19
 
23
- it "should find a doc" do
24
- doc = Invoice.find(@doc.id)
25
- doc.title.should == @doc.title
20
+ after :all do
21
+ delete_test_data(@doc, @contact)
22
+ end
23
+
24
+ it 'should find a doc' do
25
+ doc = Invoice.find(@doc.id)
26
+ doc.title.should == @doc.title
27
+ end
26
28
  end
27
- end
28
29
 
29
- describe Invoice, "a new invoice" do
30
+ context 'new' do
30
31
 
31
- before :all do
32
- @client = Client.new(:organisation=>'Invoice API-Tester')
33
- @client.save.should be_true
34
- end
35
- after :all do
36
- @client.destroy
37
- end
32
+ before :all do
33
+ @contact = Contact.new(:type=>'Client', :organisation=>'Invoice API-Tester')
34
+ @contact.save.should be_true
35
+ end
36
+ after :all do
37
+ @contact.destroy
38
+ end
38
39
 
39
- it "should create a doc" do
40
- doc = Invoice.new
41
- doc.title = 'A Document from the API'
42
- doc.notes_before = 'Your shiny new invoice [number]'
43
- doc.notes_after = 'Please pay me'
44
- doc.client_id = @client.id
45
- doc.save.should be_true
46
- doc.errors.should be_empty
47
- doc.new?.should be_false
48
- doc.notes_before.should == 'Your shiny new invoice [number]'
49
- doc.destroy
50
- end
40
+ it 'should create a doc' do
41
+ doc = Invoice.new
42
+ doc.title = 'A Document from the API'
43
+ doc.notes_before = 'Your shiny new invoice [number]'
44
+ doc.notes_after = 'Please pay me'
45
+ doc.contact_id = @contact.id
46
+ doc.save.should be_true
47
+ doc.errors.should be_empty
48
+ doc.new?.should be_false
49
+ doc.notes_before.should == 'Your shiny new invoice [number]'
50
+ doc.destroy
51
+ end
51
52
 
52
- it "should create a doc with default before after texts" do
53
- doc = Invoice.new
54
- doc.title = 'A Document from the API'
55
- doc.client_id = @client.id
56
- doc.save
57
- doc.errors.should be_empty
58
- doc.new?.should be_false
59
- doc.notes_before.should_not be_empty
60
- doc.destroy
61
- end
53
+ it 'should create a doc with default before after texts' do
54
+ doc = Invoice.new
55
+ doc.title = 'A Document from the API'
56
+ doc.contact_id = @contact.id
57
+ doc.save
58
+ doc.errors.should be_empty
59
+ doc.new?.should be_false
60
+ doc.notes_before.should_not be_empty
61
+ doc.destroy
62
+ end
63
+
64
+ it 'should fail create a doc without unique number' do
65
+ # if a test failed this invoice might still be present so try to delete
66
+ kick_existing(Invoice, '001')
67
+ doc = Invoice.new(:number=>'001')
68
+ doc.save.should == true
69
+ doc2 = Invoice.new(:number=>'001')
70
+ doc2.save.should == false
71
+ doc2.errors.count.should == 1
72
+ if doc2.errors.respond_to? :on
73
+ doc2.errors.on(:number).should == 'has already been taken'
74
+ else
75
+ doc2.errors[:number].should == ['has already been taken']
76
+ end
77
+ doc.destroy
78
+ end
62
79
 
63
- it "should fail create a doc without unique number" do
64
- # if a test failed this invoice might still be present so try to delete
65
- kick_existing(Invoice, '001')
66
- doc = Invoice.new(:number=>'001')
67
- doc.save.should == true
68
- doc2 = Invoice.new(:number=>'001')
69
- doc2.save.should == false
70
- doc2.errors.count.should == 2
71
- if doc2.errors.respond_to? :on
72
- doc2.errors.on(:number).should == "has already been taken"
73
- else
74
- doc2.errors[:number].should == ["has already been taken"]
75
- end
76
- doc.destroy
77
80
  end
78
81
 
79
- end
82
+ describe 'edit' do
80
83
 
81
- describe Invoice, "Edit an invoice" do
82
-
83
- before :all do
84
- #setup test doc to work with
85
- # create client
86
- @client = Client.new(:organisation=>'Invoice API-Tester')
87
- @client.save.should be_true
88
- @doc = Invoice.new
89
- @doc.title = 'A Document from the API'
90
- @doc.notes_before = 'Your invoice [number]'
91
- @doc.client_id = @client.id
92
- @doc.save.should be_true
93
- end
84
+ before :all do
85
+ #setup test doc to work with
86
+ # create client
87
+ @contact = Contact.new(:type=>'Client', :organisation=>'Invoice API-Tester')
88
+ @contact.save.should be_true
89
+ @doc = Invoice.new
90
+ @doc.title = 'A Document from the API'
91
+ @doc.notes_before = 'Your invoice [number]'
92
+ @doc.contact_id = @contact.id
93
+ @doc.save.should be_true
94
+ end
94
95
 
95
- after :all do
96
- delete_test_data(@doc, @client)
97
- end
96
+ after :all do
97
+ delete_test_data(@doc, @contact)
98
+ end
98
99
 
99
- it "should edit a doc" do
100
- old_lock_version = @doc.lock_version
101
- @doc.notes_before.should == 'Your invoice [number]'
102
- @doc.notes_before = 'You will recieve the amout of:'
103
- @doc.notes_after = 'Payment made to you bank Account'
104
- @doc.title = 'Changed doc title'
100
+ it 'should edit a doc' do
101
+ old_lock_version = @doc.lock_version
102
+ @doc.notes_before.should == 'Your invoice [number]'
103
+ @doc.notes_before = 'You will recieve the amout of:'
104
+ @doc.notes_after = 'Payment made to you bank Account'
105
+ @doc.title = 'Changed doc title'
105
106
 
106
- @doc.save.should be_true
107
- @doc.lock_version.should > old_lock_version # because save returns the data
108
- @doc.notes_before.should == 'You will recieve the amout of:'
109
- end
107
+ @doc.save.should be_true
108
+ @doc.lock_version.should > old_lock_version # because save returns the data
109
+ @doc.notes_before.should == 'You will recieve the amout of:'
110
+ end
110
111
 
111
- it "should fail edit with wrong number" do
112
- kick_existing(Invoice, '002')
113
- doc1 = Invoice.new(:number=>'002')
114
- doc1.save.should == true
115
- @doc.number = '002'
116
- @doc.save.should == false
117
- @doc.errors.count.should == 2
118
- if @doc.errors.respond_to? :on # TODO kick with AR 2.3
119
- @doc.errors.on(:number).should == "has already been taken"
120
- else
121
- @doc.errors[:number].should == ["has already been taken"]
122
- end
123
- doc1.destroy
112
+ it 'should fail edit with wrong number' do
113
+ kick_existing(Invoice, '002')
114
+ doc1 = Invoice.new(:number=>'002')
115
+ doc1.save.should == true
116
+ @doc.number = '002'
117
+ @doc.save.should == false
118
+ @doc.errors.count.should == 1
119
+ if @doc.errors.respond_to? :on # TODO kick with AR 2.3
120
+ @doc.errors.on(:number).should == 'has already been taken'
121
+ else
122
+ @doc.errors[:number].should == ['has already been taken']
123
+ end
124
+ doc1.destroy
125
+ end
124
126
  end
125
- end
126
127
 
127
- describe Invoice, "with line items" do
128
+ describe 'with line items' do
128
129
 
129
- before :all do
130
- @client = Client.new(:organisation=>'Credit Note API-Tester')
131
- @client.save.should be_true
132
- #setup test doc to work with
133
- @doc = Invoice.new(:client_id => @client.id,
134
- :line_items => [{ :position=>1, :description => 'Pork Chops',
135
- :quantity => 12, :price_single =>'10.00' }] )
136
- @doc.save.should be_true
137
- end
130
+ before :all do
131
+ @contact = Contact.new(:type=>'Client', :organisation=>'Credit Note API-Tester')
132
+ @contact.save.should be_true
133
+ #setup test doc to work with
134
+ @doc = Invoice.new(:contact_id => @contact.id,
135
+ :line_items => [{ :position=>1, :description => 'Pork Chops',
136
+ :quantity => 12, :price_single =>'10.00' }] )
137
+ @doc.save.should be_true
138
+ end
138
139
 
139
- after :all do
140
- delete_test_data(@doc, @client)
141
- end
140
+ after :all do
141
+ delete_test_data(@doc, @contact)
142
+ end
142
143
 
143
- it "should create a line item" do
144
- @doc.line_items.length.should == 1
145
- @doc.line_items.first.description.should == 'Pork Chops'
146
- @doc.price_total.should == 120.0
147
- end
144
+ it 'should create a line item' do
145
+ @doc.line_items.length.should == 1
146
+ @doc.line_items.first.description.should == 'Pork Chops'
147
+ @doc.gross_total.should == 120.0
148
+ end
149
+
150
+ it 'should edit line item' do
151
+ @doc.line_items[0].description = 'Egg Sandwich'
152
+ @doc.save
153
+ @doc.line_items.length.should == 1
154
+ @doc.line_items.first.description.should == 'Egg Sandwich'
155
+ end
156
+
157
+ it 'should add line item' do
158
+ item = LineItem.new( { :position=>2, :description => 'Goat-Pie', :price_single => 10, :quantity=>10} )
159
+ product = Product.new(:name=>'Eis am Stiel', :price => 1.50, :tax=>19, :description => 'Mmmhh lecker Eis')
160
+ product.save.should be_true
161
+ item1 = LineItem.new( { :position=>3, :use_product => 1, :product_id=> product.id, :quantity => 10 } )
162
+ @doc.line_items << item
163
+ @doc.line_items << item1
164
+ @doc.save
165
+ @doc.line_items.length.should == 3
166
+ @doc.net_total.should == 235.0
167
+ @doc.gross_total.should == 237.85
168
+ end
148
169
 
149
- it "should edit line item" do
150
- @doc.line_items[0].description = 'Egg Sandwich'
151
- @doc.save
152
- @doc.line_items.length.should == 1
153
- @doc.line_items.first.description.should == 'Egg Sandwich'
154
170
  end
155
171
 
156
- it "should add line item" do
157
- item = LineItem.new( { :position=>2, :description => 'Goat-Pie', :price_single => 10, :quantity=>10} )
158
- product = Product.new(:name=>'Eis am Stiel', :price => 1.50, :tax=>19, :description => 'Mmmhh lecker Eis')
159
- product.save.should be_true
160
- item1 = LineItem.new( { :position=>3, :use_product => 1, :product_id=> product.id, :quantity => 10 } )
161
- @doc.line_items << item
162
- @doc.line_items << item1
163
- @doc.save
164
- @doc.line_items.length.should == 3
165
- @doc.price_total.should == 235.0
172
+ describe 'with items of different type' do
173
+ before :all do
174
+ @contact = Contact.new(:type=>'Client', :organisation=>'Credit Note API-Tester')
175
+ @contact.save.should be_true
176
+ @doc = Invoice.new(:contact_id => @contact.id)
177
+ end
178
+
179
+ after :all do
180
+ delete_test_data(@doc, @contact)
181
+ end
182
+
183
+ it 'should create items from array' do
184
+ @doc.items = [
185
+ { :position=>1, :name => 'Pork Chops', :quantity => 12, :price_single =>'10.00', :type=>'LineItem' },
186
+ { :position=>2, :name => 'Pork Sub Total', :type=>'SubTotalItem' },
187
+ { :position=>2, :name => 'Yummi Beef', :type=>'DividerItem' },
188
+ { :position=>3, :name => 'Beef Jerky', :description=> 'Jaw Breaker',:quantity => 1, :price_single =>'10.00', :type=>'LineItem' }
189
+ ]
190
+ @doc.save.should be_true
191
+ @doc.items.length.should == 4
192
+ @doc.gross_total.should == 130.0
193
+ end
194
+
195
+ it 'should create items from array with prefixed hashes' do
196
+ # setting type eg: :type=>'LineItem' is optional
197
+ @doc.items = [
198
+ { :line_item => { :position=>1, :name => 'Pork Chops', :quantity => 12, :price_single =>'10.00', :type=>'LineItem' }},
199
+ { :sub_total_item => { :position=>2, :name => 'Pork Sub Total' }},
200
+ { :divider_item => { :position=>2, :name => 'Yummi Beef', :type=>'DividerItem' }},
201
+ { :line_item => { :position=>3, :name => 'Beef Jerky', :description=> 'Jaw Breaker',:quantity => 1, :price_single =>'10.00' }}
202
+ ]
203
+ @doc.save.should be_true
204
+ @doc.items.length.should == 4
205
+ @doc.gross_total.should == 130.0
206
+ end
166
207
  end
167
208
 
209
+ describe 'with items and line_items' do
210
+ before :all do
211
+ @contact = Contact.new(:type=>'Client', :organisation=>'Credit Note API-Tester')
212
+ @contact.save.should be_true
213
+ @doc = Invoice.new(:contact_id => @contact.id)
214
+ end
215
+
216
+ after :all do
217
+ delete_test_data(@doc, @contact)
218
+ end
219
+
220
+ it 'should prefer line_items over items when both are present' do
221
+ @doc.items = [LineItem.new( :position=>12, :name => 'dropped', :quantity => 1, :price_single =>1, :type=>'LineItem' )]
222
+ @doc.line_items = [LineItem.new( :position=>12, :name => 'added', :quantity => 1, :price_single =>10, :type=>'LineItem' )]
223
+ @doc.save.should be_true
224
+ @doc.items.length.should == 1
225
+ @doc.gross_total.should == 10.0
226
+ end
227
+
228
+ it 'should manually remove line_items so items are used on update' do
229
+ # first save so AR loads both(items/line_items) from response
230
+ @doc.items = [ { :position=>1, :name => 'Pork Chops', :quantity => 1, :price_single =>'10.00', :type=>'LineItem' }]
231
+ @doc.save.should be_true
232
+ @doc.gross_total.should == 10.0
233
+ # edit
234
+ @doc.items << LineItem.new( :position=>2, :name => 'Puppy Seeds', :quantity => 1, :price_single =>1, :type=>'LineItem' )
235
+ @doc.line_items = nil # <= IMPORTANT part
236
+
237
+ @doc.save.should be_true
238
+ @doc.items.length.should == 2
239
+ @doc.gross_total.should == 11.0
240
+ end
241
+
242
+ end
168
243
  end
244
+
169
245
  end
@@ -0,0 +1,84 @@
1
+ require 'resources_spec_helper'
2
+
3
+ unless sk_available?
4
+ puts "Sorry cannot connect to your SalesKing server, skipping real connections tests. Please check connection settings in spec_helper"
5
+ else
6
+
7
+ describe Payment do
8
+
9
+ before :all do
10
+ @contact = Contact.new(:type=>'Client', :organisation=>'Payment API-Tester')
11
+ @contact.save.should be_true
12
+ @doc = Invoice.new
13
+ @doc.title = 'A Document from the API for payment testing'
14
+ @doc.contact_id = @contact.id
15
+ @doc.save.should be_true
16
+ end
17
+
18
+ after :all do
19
+ payments = Payment.instantiate_collection(@doc.get(:payments))
20
+ payments.each { |p| p.destroy }
21
+ @doc.status = 'draft'
22
+ @doc.save
23
+ @contact.destroy
24
+ end
25
+
26
+ describe "POST request for invoice" do
27
+ it "should create" do
28
+ p = Payment.new :amount => 10
29
+
30
+ # damn i hate active_resource
31
+ @doc.post(:payments, {}, p.encode)
32
+ payments_json = @doc.get(:payments)
33
+ payments = Payment.instantiate_collection(payments_json)
34
+
35
+ payments.first.amount.should == 10
36
+ end
37
+
38
+ it "should create with method date external_ref" do
39
+ p = Payment.new :amount => 11,
40
+ :payment_method => "bank_transfer",
41
+ :date=> Date.today,
42
+ :external_ref => 'from sdk-test'
43
+
44
+ # damn i hate active_resource
45
+ @doc.post(:payments, {}, p.encode)
46
+ payments = Payment.instantiate_collection(@doc.get(:payments))
47
+ payment = payments.detect{|p| p.amount == 11 }
48
+ payment.external_ref.should == 'from sdk-test'
49
+ payment.date.should == Date.today.strftime("%Y-%m-%d")
50
+ # method is defined on Object .. TODO rename it in SK
51
+ payment.attributes['payment_method'].should == 'bank_transfer'
52
+ end
53
+
54
+ it "should close related invoice" do
55
+ p = Payment.new :amount => 10
56
+
57
+ # damn i hate active_resource
58
+ @doc.post(:payments, {:new_doc_status=>'closed'}, p.encode)
59
+ doc = Invoice.find @doc.id
60
+ doc.status.should == 'closed'
61
+ doc.number.should be
62
+ end
63
+
64
+ end
65
+
66
+ describe "direct POST create" do
67
+ it "should create" do
68
+ # relation MUST be set
69
+ p = Payment.new :amount => 12.34, :related_object_id=>@doc.id
70
+ p.save.should be_true
71
+
72
+ payments = Payment.instantiate_collection(@doc.get(:payments))
73
+ payments.map(&:amount).should include 12.34
74
+ end
75
+ end
76
+
77
+
78
+ end
79
+
80
+ def destroy_payment
81
+
82
+ end
83
+
84
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sk_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -156,6 +156,7 @@ files:
156
156
  - MIT-LICENSE
157
157
  - README.rdoc
158
158
  - Rakefile
159
+ - ci/Gemfile_ar2
159
160
  - ci/Gemfile_ar2.lock
160
161
  - lib/sk_sdk.rb
161
162
  - lib/sk_sdk/README.rdoc
@@ -176,9 +177,10 @@ files:
176
177
  - spec/sk_sdk/base_spec.rb
177
178
  - spec/sk_sdk/oauth_spec.rb
178
179
  - spec/sk_sdk/resources/README.rdoc
179
- - spec/sk_sdk/resources/clients_spec.rb
180
+ - spec/sk_sdk/resources/contacts_spec.rb
180
181
  - spec/sk_sdk/resources/credit_note_spec.rb
181
182
  - spec/sk_sdk/resources/invoice_spec.rb
183
+ - spec/sk_sdk/resources/payment_spec.rb
182
184
  - spec/sk_sdk/resources/product_spec.rb
183
185
  - spec/sk_sdk/signed_request_spec.rb
184
186
  - spec/sk_sdk/sync_field_spec.rb
@@ -198,7 +200,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
198
200
  version: '0'
199
201
  segments:
200
202
  - 0
201
- hash: -3310092520426669956
203
+ hash: 892546568127510729
202
204
  required_rubygems_version: !ruby/object:Gem::Requirement
203
205
  none: false
204
206
  requirements:
@@ -207,7 +209,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
209
  version: '0'
208
210
  segments:
209
211
  - 0
210
- hash: -3310092520426669956
212
+ hash: 892546568127510729
211
213
  requirements: []
212
214
  rubyforge_project:
213
215
  rubygems_version: 1.8.24
@@ -1,98 +0,0 @@
1
- require 'resources_spec_helper'
2
-
3
- unless sk_available?
4
- puts "Sorry cannot connect to your SalesKing server, skipping real connections tests. Please check connection settings in spec_helper"
5
- else
6
-
7
- describe Client, "with real connection" do
8
-
9
- before :all do
10
- @client = Client.new(:organisation=>'from testing API2')
11
- @client.save
12
- end
13
-
14
- after :all do
15
- #delete test client
16
- @client.destroy
17
- lambda {
18
- client = Client.find(@client.id)
19
- }.should raise_error(ActiveResource::ResourceNotFound)
20
- end
21
-
22
- it "should save" do
23
- c = Client.new :organisation=>"Rack'n Roll"
24
- c.save.should be_true
25
- c.id.should_not be_empty
26
- c.number.should_not be_empty
27
- end
28
-
29
- it "should fail create a client" do
30
- client = Client.new(:organisation=>'from testing API2')
31
- client.bank_iban = 'safasf'
32
- client.save.should == false
33
- client.errors.count.should == 1
34
- client.errors.full_messages.should == ["Bank iban is invalid"]
35
- end
36
-
37
- it "should find a single client" do
38
- client = Client.find(@client.id)
39
- client.organisation.should == @client.organisation
40
- end
41
-
42
- it "should find clients" do
43
- clients = Client.find(:all)
44
- clients.should_not be_empty
45
- end
46
- end
47
-
48
-
49
- describe Client, "with addresses" do
50
-
51
- before :all do
52
- #setup test client to work with
53
- @client = Client.new(:organisation=>'Second from testing API2',
54
- :addresses => [{ :zip => '50374', :city => 'Cologne' }] )
55
-
56
- @client.save
57
- end
58
-
59
- after :all do
60
- @client.destroy
61
- lambda {
62
- client = Client.find(@client.id)
63
- }.should raise_error(ActiveResource::ResourceNotFound)
64
- end
65
-
66
- it "should create an address" do
67
- @client.addresses.length.should == 1
68
- @client.addresses.first.zip.should == '50374'
69
- end
70
-
71
- it "should edit an address" do
72
- @client.addresses.length.should == 1
73
- # puts @client.addresses.inspect
74
- @client.addresses[0].zip = '40001'
75
- @client.save
76
- @client.addresses.length.should == 1
77
- @client.addresses.first.zip.should == '40001'
78
- end
79
-
80
- it "should add an address" do
81
- cnt_before = @client.addresses.length
82
- adr = Address.new( { :zip => '37700', :city => 'Cologne' } )
83
- @client.addresses << adr
84
- @client.save
85
- @client.addresses.length.should == cnt_before+1
86
- end
87
-
88
- it "should destroy an address" do
89
- cnt_before = @client.addresses.length
90
- @client.addresses.last._destroy = 1
91
- @client.save
92
- @client.reload
93
- @client.addresses.length.should == cnt_before-1
94
- end
95
- end
96
-
97
-
98
- end