sk_api_schema 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/README.rdoc +21 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/json/v1.0/address.json +74 -0
- data/json/v1.0/client.json +169 -0
- data/json/v1.0/credit_note.json +122 -0
- data/json/v1.0/invoice.json +122 -0
- data/json/v1.0/line_item.json +73 -0
- data/lib/sk_api_schema.rb +1 -0
- data/lib/utils/serializer.rb +66 -0
- data/sk_api_schema.gemspec +60 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/utils/field_map_spec.rb +73 -0
- metadata +108 -0
data/.gitignore
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
= SalesKing Api Schema
|
2
|
+
|
3
|
+
SalesKing API description using JSON Schema(http://json-schema.org/)
|
4
|
+
|
5
|
+
For ruby users this project provides a gem with some basic utility functions
|
6
|
+
besides the schema. Other languages can take advantage of the raw json files.
|
7
|
+
|
8
|
+
To get a fully working ruby client take a look at http://github.com/salesking/sk-api
|
9
|
+
which will be replaced soon by a new gem at http://github.com/salesking/sk_api_activeresource
|
10
|
+
|
11
|
+
|
12
|
+
Notice: This gem is still evolving and will be used actively by salesking to deliver the api soon.
|
13
|
+
Atm the JSON files are the most interesting stuff in here.
|
14
|
+
|
15
|
+
== Install
|
16
|
+
|
17
|
+
gem install sk_api_schema
|
18
|
+
|
19
|
+
== Usage
|
20
|
+
|
21
|
+
Copyright (c) 2010 Georg Leciejewski, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "sk_api_schema"
|
10
|
+
gem.summary = %Q{SalesKing API JSON Schema}
|
11
|
+
gem.description = %Q{SalesKing API JSON schema and utility methods}
|
12
|
+
gem.email = "gl@salesking.eu"
|
13
|
+
gem.homepage = "http://github.com/salesking/sk_api_schema"
|
14
|
+
gem.authors = ["Georg Leciejewski"]
|
15
|
+
gem.add_dependency 'activesupport'
|
16
|
+
gem.add_development_dependency "rspec"
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'Default: run specs.'
|
24
|
+
task :default => :spec
|
25
|
+
|
26
|
+
spec_files = Rake::FileList["spec/**/*_spec.rb"]
|
27
|
+
|
28
|
+
desc "Run specs"
|
29
|
+
Spec::Rake::SpecTask.new do |t|
|
30
|
+
t.spec_files = spec_files
|
31
|
+
t.spec_opts = ["-c"]
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Generate code coverage"
|
35
|
+
Spec::Rake::SpecTask.new(:coverage) do |t|
|
36
|
+
t.spec_files = spec_files
|
37
|
+
t.rcov = true
|
38
|
+
t.rcov_opts = ['--exclude', 'spec,/var/lib/gems']
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Generate sk_api_activeresource documentation.'
|
42
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
43
|
+
rdoc.rdoc_dir = 'rdoc'
|
44
|
+
rdoc.title = 'SalesKing-Api JSON Schema'
|
45
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
46
|
+
rdoc.rdoc_files.include('README')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,74 @@
|
|
1
|
+
{"type":"object",
|
2
|
+
"title": "address",
|
3
|
+
"description":"An address",
|
4
|
+
"properties": {
|
5
|
+
"id": {
|
6
|
+
"description": "uuid of the adress.",
|
7
|
+
"identity":true,
|
8
|
+
"readonly":true,
|
9
|
+
"type":"string"
|
10
|
+
},
|
11
|
+
"city": {
|
12
|
+
"description": "City for the address. Must at least be present for an address.",
|
13
|
+
"type":"string"
|
14
|
+
},
|
15
|
+
"address1": {
|
16
|
+
"description": "Should contain the street or otherwise primary address information.",
|
17
|
+
"optional":true,
|
18
|
+
"type":"string"
|
19
|
+
},
|
20
|
+
"address2": {
|
21
|
+
"description": "Additional address information, like floor number",
|
22
|
+
"optional":true,
|
23
|
+
"type":"string"
|
24
|
+
},
|
25
|
+
"pobox": {
|
26
|
+
"description": "Post office box number",
|
27
|
+
"optional":true,
|
28
|
+
"type":"string"
|
29
|
+
},
|
30
|
+
"zip": {
|
31
|
+
"description": "Zip number of the city. Length must be between 4..10",
|
32
|
+
"optional":true,
|
33
|
+
"type":"string"
|
34
|
+
},
|
35
|
+
"state": {
|
36
|
+
"description": "Country state of address",
|
37
|
+
"optional":true,
|
38
|
+
"type":"string"
|
39
|
+
},
|
40
|
+
"country": {
|
41
|
+
"description": "Country of the address.",
|
42
|
+
"optional":true,
|
43
|
+
"type":"string"
|
44
|
+
},
|
45
|
+
"created_at": {
|
46
|
+
"description": "Date the object was created in SK. Never changes aftwerwards",
|
47
|
+
"format":"date-time",
|
48
|
+
"readonly":true, "type":"string"
|
49
|
+
},
|
50
|
+
"updated_at": {
|
51
|
+
"description": "Date the object was edited in SK.",
|
52
|
+
"format":"date-time",
|
53
|
+
"readonly":true,
|
54
|
+
"type":"string"
|
55
|
+
},
|
56
|
+
"address_type": {
|
57
|
+
"description": "Type of the address, as seen by vCard definition.",
|
58
|
+
"enum":["work","home"],
|
59
|
+
"optional":true,
|
60
|
+
"type":"string"
|
61
|
+
},
|
62
|
+
"lat": {
|
63
|
+
"description": "Geolocation latitude",
|
64
|
+
"optional":true,
|
65
|
+
"type":"string"
|
66
|
+
},
|
67
|
+
"long": {
|
68
|
+
"description": "Geolocation longitude",
|
69
|
+
"optional":true,
|
70
|
+
"type":"string"
|
71
|
+
},
|
72
|
+
|
73
|
+
}
|
74
|
+
}
|
@@ -0,0 +1,169 @@
|
|
1
|
+
{"type":"object",
|
2
|
+
"title": "client",
|
3
|
+
"description": "A client as seen by SalesKing",
|
4
|
+
"properties": {
|
5
|
+
"id": {
|
6
|
+
"identity":true,
|
7
|
+
"optional":true,
|
8
|
+
"readonly":true,
|
9
|
+
"type":"string"
|
10
|
+
},
|
11
|
+
"number": {
|
12
|
+
"description": "Unique number, assigned from SK numbering scheme.",
|
13
|
+
"optional":true,
|
14
|
+
"type":"string"
|
15
|
+
},
|
16
|
+
"organisation": {
|
17
|
+
"description": "Name of a company. At least this or the lastname field must be filled for new records",
|
18
|
+
"type":"string"
|
19
|
+
},
|
20
|
+
"last_name": {
|
21
|
+
"description": "Last name of a person. At least this or the organisation field must be filled for new records",
|
22
|
+
"optional":true,
|
23
|
+
"type":"string"
|
24
|
+
},
|
25
|
+
"first_name": {
|
26
|
+
"description": "First name of a person.",
|
27
|
+
"optional":true,
|
28
|
+
"type":"string"
|
29
|
+
},
|
30
|
+
"gender": {
|
31
|
+
"description": "Can be empty for a company. Is used in salutation",
|
32
|
+
"optional":true,
|
33
|
+
"enum":["male", "female"],
|
34
|
+
"type":"string"
|
35
|
+
},
|
36
|
+
"position": {
|
37
|
+
"description": "Position of a person in a company.",
|
38
|
+
"optional":true,
|
39
|
+
"type":"string"
|
40
|
+
},
|
41
|
+
"title": {
|
42
|
+
"description": "Academical title of a person e.g. Dr., Prof",
|
43
|
+
"optional":true,
|
44
|
+
"type":"string"
|
45
|
+
},
|
46
|
+
"tax_number": {
|
47
|
+
"description": "Tax number, normaly applies to a private person",
|
48
|
+
"optional":true,
|
49
|
+
"type":"string"
|
50
|
+
},
|
51
|
+
"vat_number": {
|
52
|
+
"description": "VAT number, for a company or person paying value added taxes.",
|
53
|
+
"optional":true,
|
54
|
+
"type":"string"
|
55
|
+
},
|
56
|
+
"email": {
|
57
|
+
"description": "Email address of the contact.",
|
58
|
+
"optional":true,
|
59
|
+
"type":"string"
|
60
|
+
},
|
61
|
+
"url": {
|
62
|
+
"description": "An url associated with the person, e.g its company website.",
|
63
|
+
"optional":true,
|
64
|
+
"type":"string"
|
65
|
+
},
|
66
|
+
"birthday": {
|
67
|
+
"format":"date",
|
68
|
+
"optional":true,
|
69
|
+
"type":"string"
|
70
|
+
},
|
71
|
+
"tag_list": {
|
72
|
+
"description": "Space seperated list of tags.",
|
73
|
+
"optional":true,
|
74
|
+
"type":"string"
|
75
|
+
},
|
76
|
+
"created_at": {
|
77
|
+
"description": "Date the record was created in SK. Never changes afterwards.",
|
78
|
+
"format":"date-time",
|
79
|
+
"optional":true,
|
80
|
+
"readonly":true,
|
81
|
+
"type":"string"
|
82
|
+
},
|
83
|
+
"updated_at": {
|
84
|
+
"description": "Last date when the record was edited.",
|
85
|
+
"format":"date-time",
|
86
|
+
"optional":true,
|
87
|
+
"readonly":true,
|
88
|
+
"type":"string"
|
89
|
+
},
|
90
|
+
"bank_number": {
|
91
|
+
"description": "Number of the bank",
|
92
|
+
"optional":true,
|
93
|
+
"type":"string"
|
94
|
+
},
|
95
|
+
"bank_name": {
|
96
|
+
"description": "Name of the bank.",
|
97
|
+
"optional":true,
|
98
|
+
"type":"string"
|
99
|
+
},
|
100
|
+
"bank_account_number": {
|
101
|
+
"description": "Number of the bank account.",
|
102
|
+
"optional":true,
|
103
|
+
"type":"string"
|
104
|
+
},
|
105
|
+
"bank_iban": {
|
106
|
+
"description": "IBAN Number of the bank account. Is validated",
|
107
|
+
"optional":true,
|
108
|
+
"type":"string"
|
109
|
+
},
|
110
|
+
"bank_swift": {
|
111
|
+
"description": "SWIFT BIC- Bank Identifier Code",
|
112
|
+
"optional":true,
|
113
|
+
"type":"string"
|
114
|
+
},
|
115
|
+
"bank_owner": {
|
116
|
+
"description": "Owner of the bank account.",
|
117
|
+
"optional":true,
|
118
|
+
"type":"string"
|
119
|
+
},
|
120
|
+
"phone_fax": {
|
121
|
+
"description": "Fax number",
|
122
|
+
"optional":true,
|
123
|
+
"type":"string"
|
124
|
+
},
|
125
|
+
"phone_office": {
|
126
|
+
"description": "Office phone number",
|
127
|
+
"optional":true,
|
128
|
+
"type":"string"
|
129
|
+
},
|
130
|
+
"phone_home": {
|
131
|
+
"description": "Private phone number.",
|
132
|
+
"optional":true,
|
133
|
+
"type":"string"
|
134
|
+
},
|
135
|
+
"phone_mobile": {
|
136
|
+
"description": "Mobile phone number",
|
137
|
+
"optional":true,
|
138
|
+
"type":"string"
|
139
|
+
},
|
140
|
+
"lock_version": {
|
141
|
+
"description": "Increased on every edit, so SK can detect/prevent a concurrent edit by another user. First save wins.",
|
142
|
+
"optional":true,
|
143
|
+
"readonly":true,
|
144
|
+
"type":"integer"
|
145
|
+
},
|
146
|
+
"cash_discount": {
|
147
|
+
"description": "Default cash discount for new invoices.",
|
148
|
+
"optional":true,
|
149
|
+
"type":"number"
|
150
|
+
},
|
151
|
+
"due_days": {
|
152
|
+
"description": "Default due days for new invoices.",
|
153
|
+
"optional":true,
|
154
|
+
"type":"integer"
|
155
|
+
},
|
156
|
+
"address_field": {
|
157
|
+
"description": "Returns the address field used on new docs. Consist of Organisation name and default(first) address",
|
158
|
+
"optional":true,
|
159
|
+
"readonly":true,
|
160
|
+
"type":"string"
|
161
|
+
},
|
162
|
+
"addresses": {
|
163
|
+
"description": "A client can have many addresses, sorted by date descending(new first). Default address is the most recent one.",
|
164
|
+
"optional":true,
|
165
|
+
"type":"array",
|
166
|
+
"properties" : {"$ref":"./addresses.json#properties"}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
{ "type":"object",
|
2
|
+
"title": "credit note",
|
3
|
+
"description": "A credit note",
|
4
|
+
"properties":{
|
5
|
+
"id":{
|
6
|
+
"description": "UUID assigned by SK",
|
7
|
+
"identity":true,
|
8
|
+
"optional":true,
|
9
|
+
"readonly":true,
|
10
|
+
"type":"string"
|
11
|
+
},
|
12
|
+
"number":{
|
13
|
+
"description": "Unique number assigned by SK credit note number schema. Auto-assigned when document is opened. Required unless doc status is draft.",
|
14
|
+
"optional":true,
|
15
|
+
"type":"string"
|
16
|
+
},
|
17
|
+
"address_field":{
|
18
|
+
"description": "Address field with the receiver. Shown in envelope window.",
|
19
|
+
"optional":true,
|
20
|
+
"type":"string"
|
21
|
+
},
|
22
|
+
"date":{
|
23
|
+
"description": "Date the credit note is issued. Automatically set when document is opened. Required unless doc status is draft.",
|
24
|
+
"format":"date",
|
25
|
+
"optional":true,
|
26
|
+
"type":"string"
|
27
|
+
},
|
28
|
+
"due_days":{
|
29
|
+
"description": "Used to calculate the due date of the credit note. Useless if date and due date are present.",
|
30
|
+
"optional":true,
|
31
|
+
"type":"integer"
|
32
|
+
},
|
33
|
+
"due_date":{
|
34
|
+
"description": "Auto-calculated from date + due days if empty and the document is opened.",
|
35
|
+
"format":"date",
|
36
|
+
"optional":true,
|
37
|
+
"type":"string"
|
38
|
+
},
|
39
|
+
"status":{
|
40
|
+
"description": "A new document is always a draft unless otherwise stated. Only draft documents can be deleted. When a doc is opened it's number, date and due date are auto-set",
|
41
|
+
"optional":true,
|
42
|
+
"default":"draft",
|
43
|
+
"enum":["draft","open","closed"],
|
44
|
+
"type":"string"
|
45
|
+
},
|
46
|
+
"payment_method":{
|
47
|
+
"description": "How the document is beeing payed. Used in new payments.",
|
48
|
+
"optional":true,
|
49
|
+
"enum":["cash","bank_transfer","credit_card","paypal","direct_debit","cheque"],
|
50
|
+
"type":"string"
|
51
|
+
},
|
52
|
+
"title":{
|
53
|
+
"description": "The headline of a document. Use SK placeholders to prevent exessive typing e.g. 'Your credit note [number]'",
|
54
|
+
"optional":true,
|
55
|
+
"type":"string"
|
56
|
+
},
|
57
|
+
"notes_before":{
|
58
|
+
"description": "Notes shown before the line items. Normaly contains salutation and other introductional information. SK placeholders can be used.",
|
59
|
+
"optional":true,
|
60
|
+
"type":"string"
|
61
|
+
},
|
62
|
+
"notes_after":{
|
63
|
+
"description": "Notes shown after the line items. Can contain information about payments, bank account or a thank-you message. SK placeholders can be used.",
|
64
|
+
"optional":true,
|
65
|
+
"type":"string"
|
66
|
+
},
|
67
|
+
"tag_list": {
|
68
|
+
"description": "Space seperated list of tags.",
|
69
|
+
"optional":true,
|
70
|
+
"type":"string"
|
71
|
+
},
|
72
|
+
"client":{
|
73
|
+
"description": "The client for the document. New documents cannot create a client, use client_id field to set it.",
|
74
|
+
"optional":true,
|
75
|
+
"readonly":true,
|
76
|
+
"type":"object",
|
77
|
+
"properties":{"$ref":"./client.json#properties"}
|
78
|
+
},
|
79
|
+
"client_id":{
|
80
|
+
"description": "The clients uuid, must be set for a new document. New documents take the clients address field, due days and cash discount if those fields are not set.",
|
81
|
+
"type":"string"
|
82
|
+
},
|
83
|
+
"line_items":{
|
84
|
+
"description": "Line items for the document",
|
85
|
+
"optional":true,
|
86
|
+
"type":"array",
|
87
|
+
"properties":{"$ref":"./address.json#properties"}
|
88
|
+
},
|
89
|
+
"created_at":{
|
90
|
+
"description": "Date the object was created in SK. Never changes aftwerwards.",
|
91
|
+
"format":"date-time",
|
92
|
+
"optional":true,
|
93
|
+
"readonly":true,
|
94
|
+
"type":"string"
|
95
|
+
},
|
96
|
+
"updated_at":{
|
97
|
+
"description": "Date the object was edited in SK.",
|
98
|
+
"format":"date-time",
|
99
|
+
"optional":true,
|
100
|
+
"readonly":true,
|
101
|
+
"type":"string"
|
102
|
+
},
|
103
|
+
"lock_version":{
|
104
|
+
"description": "Auto-incremented by SK to prevent concurrent updateing. First save wins.",
|
105
|
+
"optional":true,
|
106
|
+
"readonly":true,
|
107
|
+
"type":"integer"
|
108
|
+
},
|
109
|
+
"price_total":{
|
110
|
+
"description": "Net total sum of all line items, 6 decimals places",
|
111
|
+
"optional":true,
|
112
|
+
"readonly":true,
|
113
|
+
"type":"number"
|
114
|
+
},
|
115
|
+
"price_tax":{
|
116
|
+
"description": "Summed up tax total of all line items, 2 decimals places",
|
117
|
+
"optional":true,
|
118
|
+
"readonly":true,
|
119
|
+
"type":"number"
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
{ "type":"object",
|
2
|
+
"title": "invoice",
|
3
|
+
"description": "An invoice",
|
4
|
+
"properties":{
|
5
|
+
"id":{
|
6
|
+
"description": "UUID assigned by SK",
|
7
|
+
"identity":true,
|
8
|
+
"optional":true,
|
9
|
+
"readonly":true,
|
10
|
+
"type":"string"
|
11
|
+
},
|
12
|
+
"number":{
|
13
|
+
"description": "Unique number assigned by SK invoice number schema. Auto-assigned when invoice is opened. Required unless doc status is draft.",
|
14
|
+
"optional":true,
|
15
|
+
"type":"string"
|
16
|
+
},
|
17
|
+
"address_field":{
|
18
|
+
"description": "Address field with the receiver. Shown in envelope window.",
|
19
|
+
"optional":true,
|
20
|
+
"type":"string"
|
21
|
+
},
|
22
|
+
"date":{
|
23
|
+
"description": "Date the invoice is issued. Automatically set when invoice is opened. Required unless doc status is draft.",
|
24
|
+
"format":"date",
|
25
|
+
"optional":true,
|
26
|
+
"type":"string"
|
27
|
+
},
|
28
|
+
"due_days":{
|
29
|
+
"description": "Used to calculate the due date of the invoice. Useless if date and due date are present.",
|
30
|
+
"optional":true,
|
31
|
+
"type":"integer"
|
32
|
+
},
|
33
|
+
"due_date":{
|
34
|
+
"description": "Auto-calculated from date + due days if empty and the invoice is opened.",
|
35
|
+
"format":"date",
|
36
|
+
"optional":true,
|
37
|
+
"type":"string"
|
38
|
+
},
|
39
|
+
"status":{
|
40
|
+
"description": "A new document is always a draft unless otherwise stated. Only draft invoices can be deleted. When a doc is opened it's number, date and due date are auto-set",
|
41
|
+
"optional":true,
|
42
|
+
"default":"draft",
|
43
|
+
"enum":["draft","open","closed"],
|
44
|
+
"type":"string"
|
45
|
+
},
|
46
|
+
"payment_method":{
|
47
|
+
"description": "How the invoce is beeing payed. Used in new payments.",
|
48
|
+
"optional":true,
|
49
|
+
"enum":["cash","bank_transfer","credit_card","paypal","direct_debit","cheque"],
|
50
|
+
"type":"string"
|
51
|
+
},
|
52
|
+
"title":{
|
53
|
+
"description": "The headline of a document. Use SK placeholders to prevent exessive typing e.g. 'Your invoice [number]'",
|
54
|
+
"optional":true,
|
55
|
+
"type":"string"
|
56
|
+
},
|
57
|
+
"notes_before":{
|
58
|
+
"description": "Notes shown before the line items. Normaly contains salutation and other introductional information. SK placeholders can be used.",
|
59
|
+
"optional":true,
|
60
|
+
"type":"string"
|
61
|
+
},
|
62
|
+
"notes_after":{
|
63
|
+
"description": "Notes shown after the line items. Can contain information about payments, bank account or a thank-you message. SK placeholders can be used.",
|
64
|
+
"optional":true,
|
65
|
+
"type":"string"
|
66
|
+
},
|
67
|
+
"tag_list": {
|
68
|
+
"description": "Space seperated list of tags.",
|
69
|
+
"optional":true,
|
70
|
+
"type":"string"
|
71
|
+
},
|
72
|
+
"client":{
|
73
|
+
"description": "The client for the document. New documents cannot create a client, use client_id field to set it.",
|
74
|
+
"optional":true,
|
75
|
+
"readonly":true,
|
76
|
+
"type":"object",
|
77
|
+
"properties":{"$ref":"./client.json#properties"}
|
78
|
+
},
|
79
|
+
"client_id":{
|
80
|
+
"description": "The clients uuid, must be set for a new document. New invoices take the clients address field, due days and cash discount if those fields are not set.",
|
81
|
+
"type":"string"
|
82
|
+
},
|
83
|
+
"line_items":{
|
84
|
+
"description": "Line items for the document",
|
85
|
+
"optional":true,
|
86
|
+
"type":"array",
|
87
|
+
"properties":{"$ref":"./address.json#properties"}
|
88
|
+
},
|
89
|
+
"created_at":{
|
90
|
+
"description": "Date the object was created in SK. Never changes aftwerwards.",
|
91
|
+
"format":"date-time",
|
92
|
+
"optional":true,
|
93
|
+
"readonly":true,
|
94
|
+
"type":"string"
|
95
|
+
},
|
96
|
+
"updated_at":{
|
97
|
+
"description": "Date the object was edited in SK.",
|
98
|
+
"format":"date-time",
|
99
|
+
"optional":true,
|
100
|
+
"readonly":true,
|
101
|
+
"type":"string"
|
102
|
+
},
|
103
|
+
"lock_version":{
|
104
|
+
"description": "Auto-incremented by SK to prevent concurrent updateing. First save wins.",
|
105
|
+
"optional":true,
|
106
|
+
"readonly":true,
|
107
|
+
"type":"integer"
|
108
|
+
},
|
109
|
+
"price_total":{
|
110
|
+
"description": "Net total sum of all line items, 6 decimals places",
|
111
|
+
"optional":true,
|
112
|
+
"readonly":true,
|
113
|
+
"type":"number"
|
114
|
+
},
|
115
|
+
"price_tax":{
|
116
|
+
"description": "Summed up tax total of all line items, 2 decimals places",
|
117
|
+
"optional":true,
|
118
|
+
"readonly":true,
|
119
|
+
"type":"number"
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
{ "type":"object",
|
2
|
+
"title": "line item",
|
3
|
+
"description": "A line item for a document",
|
4
|
+
"properties":{
|
5
|
+
"id":{
|
6
|
+
"description": "uuid of the item.",
|
7
|
+
"identity":true,
|
8
|
+
"readonly":true,
|
9
|
+
"type":"string"
|
10
|
+
},
|
11
|
+
"position":{
|
12
|
+
"description": "Required since items are sorted by position.",
|
13
|
+
"type":"integer"
|
14
|
+
},
|
15
|
+
"name":{
|
16
|
+
"description": "The name of an item",
|
17
|
+
"optional":true,
|
18
|
+
"type":"string"
|
19
|
+
},
|
20
|
+
"description":{
|
21
|
+
"description": "Item description",
|
22
|
+
"optional":true,
|
23
|
+
"type":"string"
|
24
|
+
},
|
25
|
+
"price_single":{
|
26
|
+
"description": "Net price of a single item",
|
27
|
+
"type":"number"
|
28
|
+
},
|
29
|
+
"tax":{
|
30
|
+
"description": "Tax percent for a single item.",
|
31
|
+
"optional":true,
|
32
|
+
"type":"number"
|
33
|
+
},
|
34
|
+
"discount":{
|
35
|
+
"description": "Discount in percent applied to the items net total",
|
36
|
+
"optional":true,
|
37
|
+
"type":"number"
|
38
|
+
},
|
39
|
+
"quantity_unit":{
|
40
|
+
"description": "Unit like kg, days, month.",
|
41
|
+
"optional":true,
|
42
|
+
"type":"string"
|
43
|
+
},
|
44
|
+
"quantity":{
|
45
|
+
"description": "Quantity of the item.",
|
46
|
+
"type":"number"
|
47
|
+
},
|
48
|
+
"product_id":{
|
49
|
+
"description": "An item can reference a product by its uuid. See use_product",
|
50
|
+
"optional":true,
|
51
|
+
"type":"string"
|
52
|
+
},
|
53
|
+
"use_product":{
|
54
|
+
"description": "If set and product_id is present, the products name, description, quantity, unit, price are copied if the according item fields are missing.",
|
55
|
+
"optional":true,
|
56
|
+
"type":"integer"
|
57
|
+
},
|
58
|
+
"created_at":{
|
59
|
+
"description": "Date the object was created in SK. Never changes aftwerwards",
|
60
|
+
"format":"date-time",
|
61
|
+
"optional":true,
|
62
|
+
"readonly":true,
|
63
|
+
"type":"string"
|
64
|
+
},
|
65
|
+
"updated_at":{
|
66
|
+
"description": "Date the object was edited in SK.",
|
67
|
+
"format":"date-time",
|
68
|
+
"optional":true,
|
69
|
+
"readonly":true,
|
70
|
+
"type":"string"
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'activesupport'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module SKApi
|
2
|
+
module Utils
|
3
|
+
# Mixed into Resources::Base providing to_hash and to_json serialisation for
|
4
|
+
# SKApi Resources.
|
5
|
+
# Inside SalesKing this serialising is used to render the output.
|
6
|
+
# f.ex. in the clients api controller
|
7
|
+
# => SKApi::Resources::Client.to_json(a_client)
|
8
|
+
# This way you can keep your API client up to date by using the resources and
|
9
|
+
# relying on SKApi::Resources::Client.schema
|
10
|
+
module Serializer
|
11
|
+
def self.included(base)
|
12
|
+
base.extend ClassMethods
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
def schema_to_hash
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# Create a Hash with the available (api)object attributes defined in api_fields.
|
22
|
+
#
|
23
|
+
# ==== Parameter
|
24
|
+
# obj<object>:. An ruby object which is returned as hash
|
25
|
+
def to_hash_from_schema(obj)
|
26
|
+
# first set the root node to the objects class name as symbol
|
27
|
+
obj_class_name = obj.class.name.split('::').last.underscore
|
28
|
+
# obj_class_name = obj.class.to_s.underscore.to_sym
|
29
|
+
data = { obj_class_name => {} }
|
30
|
+
# iterate over the defined api fields hash
|
31
|
+
self.schema_props.each do |field, props|
|
32
|
+
if props['type'] == 'array'
|
33
|
+
# always set the field, so the user can expect an empty array
|
34
|
+
data[obj_class_name][field] = []
|
35
|
+
if rel_objects = obj.send( field )
|
36
|
+
rel_objects.each do |rel_obj|
|
37
|
+
# setup scope for related class
|
38
|
+
klass = "SKApi::Resources::#{rel_obj.class}".constantize
|
39
|
+
# call related objects to_hash_from_schema method ex: data[:client][:addresses] << SKApi::Models::Address.to_hash_from_schema(object)
|
40
|
+
data[obj_class_name][field] << klass.to_hash_from_schema(rel_obj)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
elsif props['type'] == 'object' # a singular resource TODO should we add an empty object?
|
44
|
+
if rel_obj = obj.send( field )
|
45
|
+
klass = "SKApi::Resources::#{rel_obj.class}".constantize
|
46
|
+
# ex: data['invoice']['client'] = SKApi::Models::Client.to_hash_from_schema(client)
|
47
|
+
data[obj_class_name][field] = klass.to_hash_from_schema(rel_obj)
|
48
|
+
end
|
49
|
+
else # a simple field which can be directly called, only added of objects know its
|
50
|
+
data[obj_class_name][field] = obj.send(field) if obj.respond_to?(field.to_sym)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
data
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_json(obj)
|
57
|
+
data = self.to_hash_from_schema(obj)
|
58
|
+
# data[:links] = self.api_links
|
59
|
+
ActiveSupport::JSON.encode(data)
|
60
|
+
end
|
61
|
+
|
62
|
+
end #ClassMethods
|
63
|
+
|
64
|
+
end #mixin
|
65
|
+
end #utils
|
66
|
+
end #SKApi
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sk_api_schema}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Georg Leciejewski"]
|
12
|
+
s.date = %q{2010-11-08}
|
13
|
+
s.description = %q{SalesKing API JSON schema and utility methods}
|
14
|
+
s.email = %q{gl@salesking.eu}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".gitignore",
|
20
|
+
"README.rdoc",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"json/v1.0/address.json",
|
24
|
+
"json/v1.0/client.json",
|
25
|
+
"json/v1.0/credit_note.json",
|
26
|
+
"json/v1.0/invoice.json",
|
27
|
+
"json/v1.0/line_item.json",
|
28
|
+
"lib/sk_api_schema.rb",
|
29
|
+
"lib/utils/serializer.rb",
|
30
|
+
"sk_api_schema.gemspec",
|
31
|
+
"spec/spec_helper.rb",
|
32
|
+
"spec/utils/field_map_spec.rb"
|
33
|
+
]
|
34
|
+
s.homepage = %q{http://github.com/salesking/sk_api_schema}
|
35
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.3.7}
|
38
|
+
s.summary = %q{SalesKing API JSON Schema}
|
39
|
+
s.test_files = [
|
40
|
+
"spec/spec_helper.rb",
|
41
|
+
"spec/utils/field_map_spec.rb"
|
42
|
+
]
|
43
|
+
|
44
|
+
if s.respond_to? :specification_version then
|
45
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
50
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
53
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
54
|
+
end
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe SKApi::Utils::FieldMap do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@loc_obj = LocalContact.new
|
7
|
+
@rem_obj = RemoteContact.new()
|
8
|
+
@map = SKApi::Utils::FieldMap.new(@loc_obj, @rem_obj, map_hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should create a mapping" do
|
12
|
+
@map.outdated?.should be_false # both objects are empty
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should find outdated fields" do
|
16
|
+
@loc_obj.firstname = 'theo'
|
17
|
+
@map.outdated?.should be_true
|
18
|
+
@map.outdated.first[:loc_key].should == :firstname
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should update outdated remote fields" do
|
22
|
+
@loc_obj.firstname = 'theo'
|
23
|
+
@map.update_remote_outdated
|
24
|
+
@rem_obj.first_name.should == @loc_obj.firstname
|
25
|
+
# test logging
|
26
|
+
@map.log.should_not be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should update outdated local fields" do
|
30
|
+
@rem_obj.first_name = 'Heinz'
|
31
|
+
@map.update_local_outdated
|
32
|
+
@rem_obj.first_name.should == @loc_obj.firstname
|
33
|
+
@map.log.length.should == 1
|
34
|
+
end
|
35
|
+
# it "should update outdated local fields" do
|
36
|
+
# @rem_obj.first_name = 'Heinz'
|
37
|
+
# @map.outdated?
|
38
|
+
# @map.update_local_outdated
|
39
|
+
# @rem_obj.first_name.should == @loc_obj.firstname
|
40
|
+
# end
|
41
|
+
|
42
|
+
def map_hash
|
43
|
+
[
|
44
|
+
{:loc_key => :firstname, :rem_key => :first_name},
|
45
|
+
{:loc_key => :street, :rem_key => :address1},
|
46
|
+
{:loc_key => :postcode, :rem_key => :zip},
|
47
|
+
{:loc_key => :city, :rem_key => :city},
|
48
|
+
{:loc_key => :gender, :rem_key => :gender, :trans => { :obj=>'TransferFunctions',
|
49
|
+
:loc_trans => 'set_local_gender',
|
50
|
+
:rem_trans => 'set_remote_gender'}
|
51
|
+
}
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class RemoteContact
|
58
|
+
attr_accessor :first_name, :address1, :zip, :city, :gender
|
59
|
+
end
|
60
|
+
class LocalContact
|
61
|
+
attr_accessor :firstname, :street, :postcode, :city, :gender
|
62
|
+
end
|
63
|
+
|
64
|
+
class TransferFunctions
|
65
|
+
def self.set_local_gender(remote_val)
|
66
|
+
return 'male' if remote_val == 'm'
|
67
|
+
return 'female' if remote_val == 'f'
|
68
|
+
end
|
69
|
+
def self.set_remote_gender(local_val)
|
70
|
+
return 'm' if local_val == 'male'
|
71
|
+
return 'f' if local_val == 'female'
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sk_api_schema
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Georg Leciejewski
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-08 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activesupport
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description: SalesKing API JSON schema and utility methods
|
50
|
+
email: gl@salesking.eu
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files:
|
56
|
+
- README.rdoc
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- README.rdoc
|
60
|
+
- Rakefile
|
61
|
+
- VERSION
|
62
|
+
- json/v1.0/address.json
|
63
|
+
- json/v1.0/client.json
|
64
|
+
- json/v1.0/credit_note.json
|
65
|
+
- json/v1.0/invoice.json
|
66
|
+
- json/v1.0/line_item.json
|
67
|
+
- lib/sk_api_schema.rb
|
68
|
+
- lib/utils/serializer.rb
|
69
|
+
- sk_api_schema.gemspec
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
- spec/utils/field_map_spec.rb
|
72
|
+
has_rdoc: true
|
73
|
+
homepage: http://github.com/salesking/sk_api_schema
|
74
|
+
licenses: []
|
75
|
+
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options:
|
78
|
+
- --charset=UTF-8
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
hash: 3
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
requirements: []
|
100
|
+
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.3.7
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: SalesKing API JSON Schema
|
106
|
+
test_files:
|
107
|
+
- spec/spec_helper.rb
|
108
|
+
- spec/utils/field_map_spec.rb
|