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 +2 -3
- data/README.rdoc +1 -1
- data/ci/Gemfile_ar2 +11 -0
- data/lib/sk_sdk/README.rdoc +25 -23
- data/lib/sk_sdk/ar_patches/ar2/base.rb +7 -1
- data/lib/sk_sdk/ar_patches/ar3/base.rb +7 -1
- data/lib/sk_sdk/version.rb +1 -1
- data/spec/resources_spec_helper.rb +6 -9
- data/spec/sk_sdk/base_spec.rb +7 -7
- data/spec/sk_sdk/resources/contacts_spec.rb +100 -0
- data/spec/sk_sdk/resources/credit_note_spec.rb +12 -25
- data/spec/sk_sdk/resources/invoice_spec.rb +212 -136
- data/spec/sk_sdk/resources/payment_spec.rb +84 -0
- metadata +6 -4
- data/spec/sk_sdk/resources/clients_spec.rb +0 -98
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
data/ci/Gemfile_ar2
ADDED
data/lib/sk_sdk/README.rdoc
CHANGED
@@ -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
|
73
|
+
class Contact < SK::SDK::Base;end
|
74
74
|
|
75
75
|
# connection using BasicAuth
|
76
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
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[
|
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/
|
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/
|
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
|
-
"
|
138
|
-
{ "
|
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/
|
151
|
-
"next": "/api/
|
152
|
-
"self": "/api/
|
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
|
171
|
-
GET xy.salesking.eu/api/documents?filter[
|
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/
|
197
|
+
PUT /api/contacts/:id
|
198
198
|
{
|
199
|
-
'
|
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/
|
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
|
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
|
data/lib/sk_sdk/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
# create all classes and set their connection
|
3
|
-
%w[
|
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
|
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.
|
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
|
|
data/spec/sk_sdk/base_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'resources_spec_helper'
|
3
3
|
|
4
|
-
class
|
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 =
|
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 =
|
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 =
|
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 =
|
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
|
-
|
49
|
+
Contact.new({ :first_name => 'herbert' }, true)
|
50
50
|
else
|
51
|
-
|
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
|
-
|
12
|
-
@
|
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.
|
15
|
+
@doc.contact_id = @contact.id
|
17
16
|
@doc.save.should be_true
|
18
17
|
end
|
19
18
|
|
20
19
|
after :all do
|
21
|
-
|
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 ==
|
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 ==
|
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
|
-
@
|
88
|
-
@
|
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 :
|
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
|
-
@
|
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.
|
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.
|
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
|
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
|
7
|
+
describe Invoice do
|
9
8
|
|
10
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
30
|
+
context 'new' do
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
82
|
+
describe 'edit' do
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
96
|
+
after :all do
|
97
|
+
delete_test_data(@doc, @contact)
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
128
|
+
describe 'with line items' do
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
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
|
-
|
140
|
-
|
141
|
-
|
140
|
+
after :all do
|
141
|
+
delete_test_data(@doc, @contact)
|
142
|
+
end
|
142
143
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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.
|
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/
|
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:
|
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:
|
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
|