collmex-ruby 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/collmex.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'collmex/api'
2
+ require 'collmex/request'
3
+
4
+ module Collmex
5
+
6
+ class << self
7
+ attr_accessor :customer_id
8
+ attr_accessor :username
9
+ attr_accessor :password
10
+
11
+ def csv_opts
12
+ {
13
+ :col_sep => ";"
14
+ }
15
+ end
16
+
17
+
18
+ def setup_login_data
19
+ config = YAML.load_file('config/collmex_config.yml')["development"]
20
+ Collmex.username = config["username"]
21
+ Collmex.password = config["password"]
22
+ Collmex.customer_id = config["customer_id"]
23
+ end
24
+
25
+ def reset_login_data
26
+ Collmex.username = "000000"
27
+ Collmex.password = "000000"
28
+ Collmex.customer_id = "000000"
29
+ end
30
+ end
31
+ end
32
+
33
+ Collmex.reset_login_data
34
+
35
+
@@ -0,0 +1,361 @@
1
+ require "csv"
2
+
3
+ module Collmex
4
+ module Api
5
+
6
+ def self.is_a_collmex_api_line_obj? obj
7
+ obj.class.name =~ /Collmex\:\:Api/
8
+ end
9
+
10
+ def self.line_class_exists?(class_name)
11
+ klass = Collmex::Api.const_get(class_name)
12
+ return klass.is_a?(Class)
13
+ rescue NameError
14
+ return false
15
+ end
16
+
17
+ def self.parse_line(line)
18
+ if line.is_a?(Array) and line.first.is_a?(String)
19
+ identifyer = line.first.split("_").map{ |s| s.downcase.capitalize }.join
20
+ if self.line_class_exists?(identifyer)
21
+ Collmex::Api.const_get(identifyer).new(line)
22
+ else
23
+ raise "Could not find a Collmex::Api::Line class for \"#{identifyer}\""
24
+ end
25
+ elsif line.is_a?(String) && parsed_line = CSV.parse_line(line, Collmex.csv_opts)
26
+ identifyer = parsed_line.first.split("_").map{ |s| s.downcase.capitalize }.join
27
+ if self.line_class_exists?(identifyer)
28
+ Collmex::Api.const_get(identifyer).new(parsed_line)
29
+ else
30
+ raise "Could not find a Collmex::Api::Line class for \"#{identifyer}\""
31
+ end
32
+ else
33
+ raise "Could not parse a Collmex::Api Line from #{line.inspect}"
34
+ end
35
+ end
36
+
37
+ def self.parse_field(value, type, opts = nil)
38
+ case type
39
+ when :string then value.to_s
40
+ when :date then Date.parse(value.to_s) unless value.nil?
41
+ when :int then value.to_i unless value.nil?
42
+ when :integer then value.to_i unless value.nil?
43
+ when :float then value.to_s.gsub(',','.').to_f unless value.nil?
44
+ when :currency then Collmex::Api.parse_currency(value) unless value.nil?
45
+ end
46
+ end
47
+
48
+ def self.parse_currency(str)
49
+ str = str.to_s
50
+ case str
51
+ when /\A-?\d*[\,|.]\d{0,2}\z/ then (str.gsub(',','.').to_f * 100).to_i
52
+ when /\A-?\d+\z/ then str.to_i
53
+ when /\A-?((\d){1,3})*([\.]\d{3})+([,]\d{2})\z/ then (str.gsub('.','').gsub(',','.').to_f * 100).to_i
54
+ when /\A-?((\d){1,3})*([\,]\d{3})+([.]\d{2})\z/ then (str.gsub(',','').to_f * 100).to_i
55
+ when /\A-?((\d){1,3})*([\.\,]\d{3})+\z/ then str.gsub(',','').gsub('.','').to_i * 100
56
+ else str.to_i
57
+ end
58
+ end
59
+
60
+ def self.stringify(data, type)
61
+ case type
62
+ when :integer then (data.nil?)? data.to_s : data.to_i.to_s
63
+ when :string then data.to_s
64
+ when :float then sprintf("%.2f",data).gsub('.',',')
65
+ when :currency then Collmex::Api.stringify_currency(data)
66
+ when :date then data.strftime("%Y%m%d") unless data.nil?
67
+ end
68
+ end
69
+
70
+ def self.stringify_currency(data)
71
+ case
72
+ when data.is_a?(Integer) then sprintf("%.2f",(data.to_f / 100)).gsub('.',',')
73
+ when data.is_a?(Float) then sprintf("%.2f",(data.to_f)).gsub('.',',')
74
+ when data.is_a?(String)
75
+ int = self.parse_currency(data)
76
+ sprintf("%.2f",(int.to_f / 100)).gsub('.',',')
77
+ else data
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+
84
+
85
+ module Collmex
86
+ module Api
87
+ class Line
88
+
89
+ def self.specification
90
+ {}
91
+ end
92
+
93
+ def self.default_hash
94
+ hash = {}
95
+ self.specification.each_with_index do |field_spec, index|
96
+ if field_spec.has_key? :fix
97
+ hash[field_spec[:name]] = field_spec[:fix]
98
+ elsif field_spec.has_key? :default
99
+ hash[field_spec[:name]] = field_spec[:default]
100
+ else
101
+ hash[field_spec[:name]] = Collmex::Api.parse_field(nil, field_spec[:type])
102
+ end
103
+ end
104
+ hash
105
+ end
106
+
107
+ def self.hashify(data)
108
+ hash = self.default_hash
109
+ fields_spec = self.specification
110
+
111
+ if data.is_a? Array
112
+ fields_spec.each_with_index do |field_spec, index|
113
+ if !data[index].nil? && !field_spec.has_key?(:fix)
114
+ hash[field_spec[:name]] = Collmex::Api.parse_field(data[index], field_spec[:type])
115
+ end
116
+ end
117
+ elsif data.is_a? Hash
118
+ fields_spec.each_with_index do |field_spec, index|
119
+ if data.key?(field_spec[:name]) && !field_spec.has_key?(:fix)
120
+ hash[field_spec[:name]] = Collmex::Api.parse_field(data[field_spec[:name]], field_spec[:type])
121
+ end
122
+ end
123
+ elsif data.is_a?(String) && parsed = CSV.parse_line(data,Collmex.csv_opts)
124
+ fields_spec.each_with_index do |field_spec, index|
125
+ if !data[index].nil? && !field_spec.has_key?(:fix)
126
+ hash[field_spec[:name]] = Collmex::Api.parse_field(parsed[index], field_spec[:type])
127
+ end
128
+ end
129
+ end
130
+ hash
131
+ end
132
+
133
+
134
+ def initialize(arg = nil)
135
+ #puts self.class.name
136
+ @hash = self.class.default_hash
137
+ @hash = @hash.merge(self.class.hashify(arg)) if !arg.nil?
138
+ if self.class.specification.empty? && self.class.name.to_s != "Collmex::Api::Line"
139
+ raise "#{self.class.name} has no specification"
140
+ end
141
+ end
142
+
143
+
144
+ def to_a
145
+ array = []
146
+ self.class.specification.each do |spec|
147
+ array << @hash[spec[:name]]
148
+ end
149
+ array
150
+ end
151
+
152
+ def to_stringified_array
153
+ array = []
154
+ self.class.specification.each do |spec|
155
+ array << Collmex::Api.stringify(@hash[spec[:name]], spec[:type])
156
+ end
157
+ array
158
+ end
159
+
160
+
161
+ def to_csv
162
+ array = []
163
+ self.class.specification.each do |spec|
164
+ array << Collmex::Api.stringify(@hash[spec[:name]], spec[:type])
165
+ end
166
+ CSV.generate_line(array, Collmex.csv_opts)
167
+ end
168
+
169
+ def to_h
170
+ @hash
171
+ end
172
+
173
+
174
+ end
175
+ end
176
+ end
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+ module Collmex
185
+ module Api
186
+
187
+ class Login < Line
188
+ def self.specification
189
+ [
190
+ { name: :identifyer, type: :string, fix: "LOGIN" },
191
+ { name: :username, type: :integer },
192
+ { name: :password, type: :integer }
193
+ ]
194
+ end
195
+ end
196
+
197
+ class Cmxknd < Line
198
+ def self.specification
199
+ [
200
+ { name: :identifyer , type: :string , fix: "CMXKND" },
201
+ { name: :customer_id , type: :integer },
202
+ { name: :company_id , type: :integer , default: 1 },
203
+ { name: :salutation , type: :string },
204
+ { name: :title , type: :string },
205
+ { name: :firstname , type: :string },
206
+ { name: :lastname , type: :string },
207
+ { name: :comapyn , type: :string },
208
+ { name: :department , type: :string },
209
+ { name: :street , type: :string },
210
+ { name: :zipcode , type: :string },
211
+ { name: :city , type: :string },
212
+ { name: :annotation , type: :string },
213
+ { name: :inactive , type: :integer },
214
+ { name: :country , type: :string },
215
+ { name: :phone , type: :string },
216
+ { name: :fax , type: :string },
217
+ { name: :email , type: :string },
218
+ { name: :account_id , type: :string },
219
+ { name: :blz , type: :string },
220
+ { name: :iban , type: :string },
221
+ { name: :bic , type: :string },
222
+ { name: :bank_name , type: :string },
223
+ { name: :vat_id , type: :string },
224
+ { name: :payment_condition, type: :integer },
225
+ { name: :dscout_group , type: :integer },
226
+ { name: :deliver_conditions, type: :string },
227
+ { name: :deliver_conditions_additions, type: :string },
228
+ { name: :output_media , type: :integer },
229
+ { name: :account_owner , type: :string },
230
+ { name: :address_group , type: :integer },
231
+ { name: :ebay_member , type: :string },
232
+ { name: :price_group , type: :integer },
233
+ { name: :currency , type: :string },
234
+ { name: :agent , type: :integer },
235
+ { name: :cost_unit , type: :string },
236
+ { name: :due_to , type: :date },
237
+ { name: :delivery_ban , type: :integer },
238
+ { name: :building_servant , type: :integer },
239
+ { name: :account_id_at_customer, type: :string },
240
+ { name: :output_language , type: :integer },
241
+ { name: :email_cc , type: :string },
242
+ { name: :phone_2 , type: :string },
243
+ ]
244
+ end
245
+ end
246
+
247
+ class Message < Line
248
+ def self.specification
249
+ [
250
+ { name: :identifyer , type: :string , fix: "MESSAGE" },
251
+ { name: :type , type: :string },
252
+ { name: :id , type: :integer },
253
+ { name: :text , type: :string },
254
+ { name: :line , type: :integer },
255
+ ]
256
+ end
257
+
258
+
259
+ def success?
260
+ if @hash.has_key?(:type) && !@hash[:type].empty? && @hash[:type] == "S"
261
+ true
262
+ else
263
+ false
264
+ end
265
+ end
266
+
267
+ def result
268
+ if @hash.has_key?(:type) && !@hash[:type].empty?
269
+ case @hash[:type]
270
+ when "S" then :success
271
+ when "W" then :warning
272
+ when "E" then :error
273
+ else :undefined
274
+ end
275
+ else
276
+ :undefined
277
+ end
278
+ end
279
+ end
280
+
281
+ class CustomerGet < Line
282
+ def self.specification
283
+ [
284
+ { name: :identifyer , type: :string , fix: "CUSTOMER_GET" },
285
+ { name: :id , type: :integer },
286
+ { name: :company_id , type: :integer , default: 1 },
287
+ { name: :searchtext , type: :string },
288
+ { name: :due_to_review , type: :integer },
289
+ { name: :zip_code , type: :string },
290
+ { name: :adress_group , type: :integer },
291
+ { name: :price_group , type: :integer },
292
+ { name: :discout_group , type: :integer },
293
+ { name: :agent , type: :integer },
294
+ { name: :only_changed , type: :integer },
295
+ { name: :system_name , type: :string },
296
+ { name: :inactive , type: :integer },
297
+ ]
298
+
299
+
300
+ end
301
+ end
302
+
303
+ class AccdocGet < Line
304
+ def self.specification
305
+ [
306
+ { name: :identifyer , type: :string , fix: "ACCDOC_GET" },
307
+ { name: :company_id , type: :integer , default: 1 },
308
+ { name: :business_year , type: :integer },
309
+ { name: :id , type: :integer },
310
+ { name: :account_id , type: :integer },
311
+ { name: :cost_unit , type: :integer },
312
+ { name: :customer_id , type: :integer },
313
+ { name: :provider_id , type: :integer },
314
+ { name: :asset_id , type: :integer },
315
+ { name: :invoice_id , type: :integer },
316
+ { name: :jorney_id , type: :integer },
317
+ { name: :text , type: :string },
318
+ { name: :date_start , type: :date },
319
+ { name: :date_end , type: :date },
320
+ { name: :cancellattion , type: :integer },
321
+ { name: :changed_only , type: :integer },
322
+ { name: :system_name , type: :string },
323
+ ]
324
+ end
325
+ end
326
+
327
+ class Accdoc < Line
328
+ def self.specification
329
+ [
330
+ { name: :identifyer , type: :string , fix: "ACCDOC" },
331
+ { name: :company_id , type: :integer , default: 1 },
332
+ { name: :business_year , type: :integer },
333
+ { name: :id , type: :integer },
334
+ { name: :accdoc_date , type: :date },
335
+ { name: :accounted_date , type: :date },
336
+ { name: :test , type: :string },
337
+ { name: :position_id , type: :integer },
338
+ { name: :account_id , type: :integer },
339
+ { name: :account_name , type: :string },
340
+ { name: :should_have , type: :integer },
341
+ { name: :amount , type: :currency },
342
+ { name: :customer_id , type: :integer },
343
+ { name: :customer_name , type: :string },
344
+ { name: :provider_id , type: :integer },
345
+ { name: :provider_name , type: :string },
346
+ { name: :asset_id , type: :integer },
347
+ { name: :asset_name , type: :string },
348
+ { name: :canceled_accdoc , type: :integer },
349
+ { name: :cost_unit , type: :string },
350
+ { name: :invoice_id , type: :string },
351
+ { name: :customer_order_id, type: :integer },
352
+ { name: :jorney_id , type: :integer },
353
+ { name: :belongs_to_id , type: :integer },
354
+ { name: :belongs_to_year , type: :integer },
355
+ { name: :belongs_to_pos , type: :integer },
356
+ ]
357
+ end
358
+ end
359
+
360
+ end
361
+ end
File without changes
File without changes
@@ -0,0 +1,95 @@
1
+ require "net/http"
2
+ require "uri"
3
+
4
+ module Collmex
5
+ class Request
6
+
7
+
8
+ attr_accessor :commands, :http
9
+
10
+
11
+ def self.run(&block)
12
+ Request.new.tap do |request|
13
+ request.instance_eval &block if block_given?
14
+ request.execute
15
+ end
16
+ end
17
+
18
+
19
+ def self.classify(term)
20
+ term.to_s.split("_").collect(&:capitalize).join
21
+ end
22
+
23
+
24
+ def enqueue(command, args = {})
25
+ if command.is_a? Symbol
26
+ add_command Collmex::Api::const_get(self.class.classify(command)).new(args)
27
+ elsif Collmex::Api.is_a_collmex_api_line_obj?(command)
28
+ add_command command
29
+ else
30
+ return false
31
+ end
32
+ end
33
+
34
+
35
+ def initialize
36
+ @commands = []
37
+ @raw_response = {}
38
+
39
+ add_command Collmex::Api::Login.new({username: Collmex.username, password: Collmex.password})
40
+ end
41
+
42
+
43
+ def add_command(cmd)
44
+ @commands << cmd
45
+ cmd
46
+ end
47
+
48
+
49
+ def self.uri
50
+ URI.parse "https://www.collmex.de/cgi-bin/cgi.exe\?#{Collmex.customer_id},0,data_exchange"
51
+ end
52
+
53
+
54
+ def self.header_attributes
55
+ {"Content-Type" => "text/csv"}
56
+ end
57
+
58
+ def payload
59
+ @commands.map{ |c| c.to_csv }.join
60
+ end
61
+
62
+
63
+ def parse_response
64
+ @response = @raw_response[:array].map { |l| Collmex::Api.parse_line(l) }
65
+ @response
66
+ end
67
+
68
+ def raw_response
69
+ @raw_response
70
+ end
71
+
72
+
73
+ def response
74
+ @response
75
+ end
76
+
77
+
78
+ def execute
79
+ @http = Net::HTTP.new(Collmex::Request.uri.host, Collmex::Request.uri.port)
80
+ @http.use_ssl = true
81
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
82
+
83
+ response = @http.request_post(Collmex::Request.uri.request_uri, self.payload, Collmex::Request.header_attributes)
84
+
85
+ response.body.force_encoding("ISO8859-1") if response.body.encoding.to_s == "ASCII-8BIT"
86
+
87
+ @raw_response[:string] = response.body.encode("UTF-8")
88
+ @raw_response[:array] = CSV.parse(@raw_response[:string], Collmex.csv_opts)
89
+
90
+ return parse_response
91
+ end
92
+
93
+
94
+ end
95
+ end