sk_sdk 0.2.2 → 0.3.0

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