tec_doc 0.2.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.
Files changed (65) hide show
  1. data/LICENSE +20 -0
  2. data/README.md +29 -0
  3. data/bin/tec_doc +51 -0
  4. data/lib/tec_doc.rb +28 -0
  5. data/lib/tec_doc/article.rb +317 -0
  6. data/lib/tec_doc/article_attribute.rb +17 -0
  7. data/lib/tec_doc/article_document.rb +49 -0
  8. data/lib/tec_doc/article_oe_number.rb +11 -0
  9. data/lib/tec_doc/article_thumbnail.rb +18 -0
  10. data/lib/tec_doc/assembly_group.rb +77 -0
  11. data/lib/tec_doc/brand.rb +18 -0
  12. data/lib/tec_doc/client.rb +84 -0
  13. data/lib/tec_doc/date_parser.rb +14 -0
  14. data/lib/tec_doc/error.rb +4 -0
  15. data/lib/tec_doc/fuel_type.rb +0 -0
  16. data/lib/tec_doc/generic_article.rb +47 -0
  17. data/lib/tec_doc/language.rb +22 -0
  18. data/lib/tec_doc/vehicle.rb +121 -0
  19. data/lib/tec_doc/vehicle_manufacturer.rb +46 -0
  20. data/lib/tec_doc/vehicle_model.rb +46 -0
  21. data/lib/tec_doc/version.rb +3 -0
  22. data/spec/cassettes/article_all.yml +88 -0
  23. data/spec/cassettes/article_all_with_details.yml +84 -0
  24. data/spec/cassettes/article_details.yml +68 -0
  25. data/spec/cassettes/article_details_for_trade_number.yml +56 -0
  26. data/spec/cassettes/article_document_all.yml +49 -0
  27. data/spec/cassettes/article_document_content.yml +763 -0
  28. data/spec/cassettes/article_information.yml +55 -0
  29. data/spec/cassettes/article_linked_manufacturers.yml +45 -0
  30. data/spec/cassettes/article_linked_vehicle_ids.yml +45 -0
  31. data/spec/cassettes/article_linked_vehicles.yml +372 -0
  32. data/spec/cassettes/article_linked_vehicles_with_details.yml +430 -0
  33. data/spec/cassettes/article_search.yml +62 -0
  34. data/spec/cassettes/article_search_for_linked_manufacturers.yml +47 -0
  35. data/spec/cassettes/article_thumbnail_all.yml +45 -0
  36. data/spec/cassettes/article_thumbnail_content.yml +399 -0
  37. data/spec/cassettes/article_trade_number.yml +46 -0
  38. data/spec/cassettes/article_with_a_lot_linked_vehicles.yml +60 -0
  39. data/spec/cassettes/assembly_group_all.yml +90 -0
  40. data/spec/cassettes/assembly_group_children.yml +55 -0
  41. data/spec/cassettes/brand_all.yml +81 -0
  42. data/spec/cassettes/generic_article_all.yml +46 -0
  43. data/spec/cassettes/language_all.yml +48 -0
  44. data/spec/cassettes/linked_targets_by_manufacturers.yml +2584 -0
  45. data/spec/cassettes/status_401.yml +38 -0
  46. data/spec/cassettes/vehicle_all.yml +79 -0
  47. data/spec/cassettes/vehicle_assembly_groups.yml +83 -0
  48. data/spec/cassettes/vehicle_child_assembly_groups.yml +49 -0
  49. data/spec/cassettes/vehicle_find_by_id.yml +50 -0
  50. data/spec/cassettes/vehicle_manufacturer_all.yml +52 -0
  51. data/spec/cassettes/vehicle_model_all.yml +119 -0
  52. data/spec/spec_helper.rb +28 -0
  53. data/spec/tec_doc/article_document_spec.rb +34 -0
  54. data/spec/tec_doc/article_spec.rb +185 -0
  55. data/spec/tec_doc/article_thumbnail_spec.rb +34 -0
  56. data/spec/tec_doc/assembly_group_spec.rb +48 -0
  57. data/spec/tec_doc/brand_spec.rb +22 -0
  58. data/spec/tec_doc/client_spec.rb +11 -0
  59. data/spec/tec_doc/date_parser_spec.rb +17 -0
  60. data/spec/tec_doc/generic_article_spec.rb +30 -0
  61. data/spec/tec_doc/language_spec.rb +22 -0
  62. data/spec/tec_doc/vehicle_manufacturer_spec.rb +43 -0
  63. data/spec/tec_doc/vehicle_model_spec.rb +35 -0
  64. data/spec/tec_doc/vehicle_spec.rb +80 -0
  65. metadata +426 -0
@@ -0,0 +1,17 @@
1
+ module TecDoc
2
+ class ArticleAttribute
3
+ attr_accessor :block_no, :id, :is_conditional, :is_interval, :name, :short_name, :successor_id, :type, :unit, :value, :value_id
4
+
5
+ def initialize(attributes = {})
6
+ attributes.each do |name, value|
7
+ send("#{name.to_s.gsub(/^attr_/, '')}=", value)
8
+ end
9
+
10
+ @id = @id.to_i if @id
11
+ @value_id = @value_id.to_i if @value_id
12
+ @value = DateParser.new(@value).to_date if @type == "D"
13
+ @is_interval = (@is_interval == "true") if @is_interval.is_a?(String)
14
+ @is_conditional = (@is_conditional == "true") if @is_conditional.is_a?(String)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ module TecDoc
2
+ class ArticleDocument
3
+ attr_accessor :id, :file_name, :file_type_name, :link_id, :description, :type_id, :type_name
4
+
5
+ # Find document descriptions to an article
6
+ #
7
+ # @option options [Integer] :article_id article ID
8
+ # @option options [Integer] :article_link_id article link ID (optional)
9
+ # @option options [String] :country country code according to ISO 3166
10
+ # @option options [Integer] :doc_type_id document type (KT 141) (optional)
11
+ # @option options [String] :lang language code according to ISO 639
12
+ # @return [Array<TecDoc::ArticleDocument>] list of article documents
13
+ def self.all(options = {})
14
+ options = {
15
+ :country => TecDoc.client.country,
16
+ :lang => I18n.locale.to_s
17
+ }.merge(options)
18
+ response = TecDoc.client.request(:get_article_documents, options)
19
+ response.map do |attributes|
20
+ new attributes
21
+ end
22
+ end
23
+
24
+ def initialize(attributes = {})
25
+ @id = attributes[:doc_id].to_i
26
+ @link_id = attributes[:doc_link_id].to_i
27
+ @file_name = attributes[:doc_file_name].to_s
28
+ @file_type_name = attributes[:doc_file_type_name].to_s
29
+ @type_id = attributes[:doc_type_id].to_i
30
+ @type_name = attributes[:doc_type_name].to_s
31
+ end
32
+
33
+ def url
34
+ base_url = TecDoc.client.connection.wsdl.endpoint.gsub("/services/TecdocToCatWL", "")
35
+ provider = TecDoc.client.provider
36
+ thumbnail_flag = self.is_a?(ArticleThumbnail) ? "1" : "0"
37
+ "#{base_url}/documents/#{provider}/#{id}/#{thumbnail_flag}"
38
+ end
39
+
40
+ def content
41
+ request = TecDoc.client.connection.http
42
+ request.url = url
43
+ request.body = nil
44
+ request.headers = {}
45
+ response = HTTPI.post(request)
46
+ response.raw_body
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ module TecDoc
2
+ class ArticleOENumber
3
+ attr_accessor :block_number, :brand_name, :oe_number, :sort_number
4
+
5
+ def initialize(attributes = {})
6
+ attributes.each do |name, value|
7
+ send("#{name}=", value)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ module TecDoc
2
+ class ArticleThumbnail < ArticleDocument
3
+ # Find article thumbnail documents
4
+ #
5
+ # @option options [Integer] :article_id Article ID
6
+ # @return [Array<TecDoc::ArticleThumbnail>] list of article thumbnails
7
+ def self.all(options = {})
8
+ response = TecDoc.client.request(:get_thumbnail_by_article_id, options)
9
+ response.map do |attributes|
10
+ thumbnail = new
11
+ thumbnail.id = attributes[:thumb_doc_id].to_i
12
+ thumbnail.file_name = attributes[:thumb_file_name].to_s
13
+ thumbnail.type_id = attributes[:thumb_type_id].to_i
14
+ thumbnail
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,77 @@
1
+ module TecDoc
2
+ class AssemblyGroup
3
+ attr_accessor :id, :parent_id, :name, :has_children, :parent
4
+ attr_writer :children
5
+
6
+ attr_accessor :scope
7
+
8
+ def initialize(attributes={})
9
+ @id = attributes[:assembly_group_node_id].to_i
10
+ @name = attributes[:assembly_group_name].to_s
11
+ @has_children = attributes[:has_childs]
12
+ @scope = attributes[:scope]
13
+ if attributes[:parent_node_id]
14
+ @parent_id = attributes[:parent_node_id].to_i
15
+ end
16
+ end
17
+
18
+ # Find vehicle, axle, motor or universal assembly groups for the search tree
19
+ #
20
+ # @option options [TrueClass, FalseClass] :child_nodes include child nodes
21
+ # @option options [String] :lang language code according to ISO 639
22
+ # @option options [String] :linking_target_type linking target (C: Vehicle type, M: Motor, A: Axle, K: Body Type, U: Universal)
23
+ # @option options [Integer] :parent_node_id parent node id (optional)
24
+ # @return [Array<TecDoc::AssemblyGroup>] list of languages
25
+ def self.all(options = {})
26
+ options = {
27
+ :lang => I18n.locale.to_s
28
+ }.merge(options)
29
+
30
+ if options[:linking_target_id]
31
+ options[:country] ||= TecDoc.client.country
32
+ response = TecDoc.client.request(:get_linked_child_nodes_all_linking_target, options)
33
+ else
34
+ response = TecDoc.client.request(:get_child_nodes_all_linking_target2, options)
35
+ end
36
+
37
+ groups = response.map do |attributes|
38
+ attributes[:scope] = options
39
+ new(attributes)
40
+ end
41
+
42
+ if options[:child_nodes]
43
+ group_ids_map = {}
44
+ groups.each do |group|
45
+ group_ids_map[group.id] = group
46
+ end
47
+ groups.each do |group|
48
+ parent = group_ids_map[group.parent_id]
49
+ if parent
50
+ parent.add_child(group)
51
+ end
52
+ end
53
+ end
54
+
55
+ groups
56
+ end
57
+
58
+ def children
59
+ @children ||= if has_children
60
+ self.class.
61
+ all(scope.merge(:parent_node_id => id)).
62
+ each { |child| child.parent = self }
63
+ else
64
+ []
65
+ end
66
+ end
67
+
68
+ def add_child(child)
69
+ @children ||= []
70
+ @children << child
71
+ end
72
+
73
+ def inspect
74
+ "#<#{self.class} @id=#{id.inspect}, @parent_id=#{parent_id.inspect}, @name=#{name.inspect}, @has_children=#{has_children.inspect}>"
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,18 @@
1
+ module TecDoc
2
+ class Brand
3
+ attr_accessor :number, :name
4
+
5
+ # Get all brands available for provider.
6
+ #
7
+ # @return [Array<TecDoc::Brand>] list of brands
8
+ def self.all
9
+ response = TecDoc.client.request(:get_brands_for_assortment)
10
+ response.map do |attributes|
11
+ manufacturer = new
12
+ manufacturer.number = attributes[:brand_no].to_i
13
+ manufacturer.name = attributes[:brand_name].to_s
14
+ manufacturer
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,84 @@
1
+ module TecDoc
2
+ class Client
3
+ attr_accessor :provider, :country, :connection
4
+
5
+ def initialize(options = {})
6
+ self.provider = options[:provider]
7
+ self.country = options[:country]
8
+ self.connection = Savon::Client.new do |wsdl, http|
9
+ proxy = options[:proxy] || ENV['http_proxy']
10
+ http.proxy = proxy if proxy
11
+ end
12
+ self.mode = options[:mode] || :live
13
+ end
14
+
15
+ def request(operation, options = {})
16
+ log operation, options do
17
+ response = connection.request(operation) do
18
+ soap.body = { :in => { :provider => provider }.merge(options) }
19
+ end
20
+ # Parse errors
21
+ status_node = response.doc.xpath("//status").first
22
+ if status_node.text != "200"
23
+ status_text_node = response.doc.xpath("//statusText").first
24
+ raise Error.new(status_text_node.text)
25
+ end
26
+ # Parse the document
27
+ response.doc.xpath("//data/array/array").map do |node|
28
+ node_to_hash(node)
29
+ end
30
+ # response
31
+ end
32
+ end
33
+
34
+ def mode=(value)
35
+ if value == :test
36
+ connection.wsdl.endpoint = "http://webservicepilot.tecdoc.net/pegasus-2-0/services/TecdocToCatWL"
37
+ connection.wsdl.namespace = connection.wsdl.endpoint
38
+ @mode = :test
39
+ else
40
+ connection.wsdl.endpoint = "http://webservice-cs.tecdoc.net/pegasus-2-0/services/TecdocToCatWL"
41
+ connection.wsdl.namespace = connection.wsdl.endpoint
42
+ @mode = :live
43
+ end
44
+ end
45
+
46
+ attr_reader :mode
47
+
48
+ # Sets the logger to use.
49
+ attr_writer :logger
50
+
51
+ # Returns the logger. Defaults to an instance of +Logger+ writing to STDOUT.
52
+ def logger
53
+ @logger ||= ::Logger.new STDOUT
54
+ end
55
+
56
+ def log(operation, options)
57
+ t = Time.now
58
+ results = yield
59
+ duration = 1000.0 * (Time.now - t)
60
+ logger.info "TecDoc: #{operation.inspect} #{options.inspect} #{'(%.1fms)' % duration}"
61
+ results
62
+ end
63
+
64
+ private
65
+
66
+ def node_to_hash(node)
67
+ attributes = {}
68
+ node.children.each do |n|
69
+ if n.xpath("empty").text == "true"
70
+ attributes[n.name.snakecase.to_sym] = []
71
+ elsif (n_array = n.xpath("array/array")).size > 0
72
+ attributes[n.name.snakecase.to_sym] = n_array.map { |nn| node_to_hash(nn) }
73
+ elsif n.children.reject { |nn| nn.is_a?(Nokogiri::XML::Text) }.size > 0
74
+ attributes[n.name.snakecase.to_sym] = node_to_hash(n)
75
+ elsif n.text == ""
76
+ attributes[n.name.snakecase.to_sym] = nil
77
+ else
78
+ attributes[n.name.snakecase.to_sym] = n.text
79
+ end
80
+ end
81
+ attributes
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,14 @@
1
+ module TecDoc
2
+ class DateParser
3
+ def initialize(value)
4
+ @value = value
5
+ end
6
+
7
+ def to_date
8
+ if @value
9
+ year, month = @value.to_i.divmod(100)
10
+ Date.new(year, month, 1)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,4 @@
1
+ module TecDoc
2
+ class Error < StandardError
3
+ end
4
+ end
File without changes
@@ -0,0 +1,47 @@
1
+ module TecDoc
2
+ class GenericArticle
3
+ attr_accessor :id, :name
4
+ attr_accessor :scope
5
+
6
+ # getGenericArticlesByManufacturer5()
7
+
8
+ # Get generic articles
9
+ #
10
+ # @option options [Integer] :assembly_group_node_id (optional)
11
+ # @option options [LongList] :generic_article_id (optional)
12
+ # @option options [LongList] :brand_no result of brand selection (optional)
13
+ # @option options [String] :linking_target_type - "C", "M", "A", "K", "U"
14
+ # @option options [Integer] :linking_target_id - null if "U"
15
+ # @option options [Integer] :result_mode - 1: Distinct brand numbers, 2: Distinct generic articles, 3: Both (optional)
16
+ # @option options [Integer] :sort_mode - 1: Brand name, 2: Article norm name (optional)
17
+ # @return [Array<TecDoc::GenericArticle>] list of generic articles
18
+ def self.all(options = {})
19
+ options[:result_mode] = 2
20
+ options[:sort_mode] = 2
21
+ options = {
22
+ :lang => I18n.locale.to_s,
23
+ :country => TecDoc.client.country
24
+ }.merge(options)
25
+ TecDoc.client.request(:get_generic_articles_by_manufacturer6, options).map do |attributes|
26
+ new(attributes, options)
27
+ end
28
+ end
29
+
30
+ def initialize(attributes = {}, scope = {})
31
+ @id = (attributes[:id] || attributes[:generic_article_id]).to_i
32
+ @name = attributes[:article_norm_name]
33
+ @scope = scope
34
+ end
35
+
36
+ # Generic article linked articles
37
+ def articles(options = {})
38
+ options = {
39
+ :linking_target_type => scope[:linking_target_type],
40
+ :linking_target_id => scope[:linking_target_id]
41
+ }.merge(options).merge({
42
+ :generic_article_id => { :array => { :id => [id] } }
43
+ })
44
+ Article.all(options)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,22 @@
1
+ module TecDoc
2
+ class Language
3
+ attr_accessor :code, :name
4
+
5
+ # Get all languages available for provider.
6
+ #
7
+ # @option options [String] :lang language code according to ISO 639
8
+ # @return [Array<TecDoc::Language>] list of languages
9
+ def self.all(options = {})
10
+ options = {
11
+ :lang => I18n.locale.to_s
12
+ }.merge(options)
13
+ response = TecDoc.client.request(:get_languages, options)
14
+ response.map do |attributes|
15
+ language = new
16
+ language.code = attributes[:language_code].to_s
17
+ language.name = attributes[:language_name].to_s
18
+ language
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,121 @@
1
+ module TecDoc
2
+ class Vehicle
3
+ attr_accessor \
4
+ :id,
5
+ :name,
6
+ :cylinder_capacity,
7
+ :first_country,
8
+ :linked,
9
+ :power_hp_from,
10
+ :power_hp_to,
11
+ :power_kw_from,
12
+ :power_kw_to,
13
+ :date_of_construction_from,
14
+ :date_of_construction_to,
15
+ :motor_codes,
16
+ :manu_id,
17
+ :mod_id,
18
+ :attributes,
19
+ :article_link_id
20
+
21
+ # Find vehicles for simplified selection with motor codes
22
+ #
23
+ # @option options [Integer] :car_type vehicle type (1: Passenger car, 2: Commercial vehicle, 3: Light commercial)
24
+ # @option options [String] :countries_car_selection country code according to ISO 3166
25
+ # @option options [TrueClass, FalseClass] :country_group_flag country group selection
26
+ # @option options [String] :country_user_setting country for article assignments, country code according to assignments ISO 3166 (optional)
27
+ # @option options [Integer, NilClass] :favoured_list simplified vehicle selection (1: first list selection, 0: rest)
28
+ # @option options [String] :lang language code according to ISO 639
29
+ # @option options [TrueClass, FalseClass] :linked selection with/without article assignments (false: all, true: only linked articles)
30
+ # @option options [Integer] :manu_id manufacturer ID
31
+ # @option options [Integer] :mod_id vehicle ID
32
+ # @return [Array<TecDoc::VehicleManufacturer>] list of vehicles with motor codes
33
+ def self.all(options = {})
34
+ options = {
35
+ :car_type => 1,
36
+ :countries_car_selection => TecDoc.client.country,
37
+ :country_group_flag => false,
38
+ :favoured_list => 1,
39
+ :lang => I18n.locale.to_s,
40
+ :linked => false
41
+ }.merge(options)
42
+ response = TecDoc.client.request(:get_vehicle_simplified_selection4, options)
43
+ response.map do |attributes|
44
+ vehicle = new
45
+ car_attributes = attributes[:car_details]
46
+ if car_attributes
47
+ vehicle.manu_id = options[:manu_id].to_i
48
+ vehicle.mod_id = options[:mod_id].to_i
49
+ vehicle.id = car_attributes[:car_id].to_i
50
+ vehicle.name = car_attributes[:car_name].to_s
51
+ vehicle.cylinder_capacity = car_attributes[:cylinder_capacity].to_i
52
+ vehicle.first_country = car_attributes[:first_country].to_s
53
+ vehicle.linked = car_attributes[:linked]
54
+ vehicle.power_hp_from = car_attributes[:power_hp_from].to_i
55
+ vehicle.power_hp_to = car_attributes[:power_hp_to].to_i
56
+ vehicle.power_kw_from = car_attributes[:power_kw_from].to_i
57
+ vehicle.power_kw_to = car_attributes[:power_kw_to].to_i
58
+ vehicle.date_of_construction_from = DateParser.new(car_attributes[:year_of_constr_from]).to_date
59
+ vehicle.date_of_construction_to = DateParser.new(car_attributes[:year_of_constr_to]).to_date
60
+ end
61
+ vehicle.motor_codes = attributes[:motor_codes].map { |mc| mc[:motor_code] }
62
+ vehicle
63
+ end
64
+ end
65
+
66
+ def self.find(options = {})
67
+ id = options.delete(:id)
68
+ options = {
69
+ :car_ids => { :array => { :ids => [id] } },
70
+ :countries_car_selection => TecDoc.client.country,
71
+ :country_user_setting => TecDoc.client.country,
72
+ :country => TecDoc.client.country,
73
+ :lang => TecDoc.client.country,
74
+ :axles => false,
75
+ :cabs => false,
76
+ :country_group_flag => false,
77
+ :motor_codes => true,
78
+ :vehicle_details_2 => false,
79
+ :vehicle_terms => true
80
+ }.merge(options)
81
+ response = TecDoc.client.request(:get_vehicle_by_ids_2, options)
82
+ if attrs = response.first
83
+ details = attrs[:vehicle_details] || {}
84
+ terms = attrs[:vehicle_terms] || {}
85
+ vehicle = new
86
+ vehicle.id = attrs[:car_id].to_i
87
+ vehicle.name = terms[:car_type].to_s
88
+ vehicle.cylinder_capacity = details[:ccm_tech].to_i
89
+ vehicle.power_hp_from = details[:power_hp_from].to_i
90
+ vehicle.power_hp_to = details[:power_hp_to].to_i
91
+ vehicle.power_kw_from = details[:power_kw_from].to_i
92
+ vehicle.power_kw_to = details[:power_kw_to].to_i
93
+ vehicle.date_of_construction_from = DateParser.new(details[:year_of_constr_from]).to_date
94
+ vehicle.date_of_construction_to = DateParser.new(details[:year_of_constr_to]).to_date
95
+ vehicle.manu_id = details[:manu_id].to_i
96
+ vehicle.mod_id = details[:mod_id].to_i
97
+ vehicle.motor_codes = attrs[:motor_codes].map { |mc| mc[:motor_code] }
98
+ vehicle
99
+ else
100
+ nil
101
+ end
102
+ end
103
+
104
+ def attributes
105
+ @attributes || []
106
+ end
107
+
108
+ def attributes=(attrs)
109
+ @attributes = attrs.map{ |attr| ArticleAttribute.new(attr) }
110
+ end
111
+
112
+ # Vehicle linked assembly parent groups
113
+ def assembly_groups(options = {})
114
+ options.merge!({
115
+ :linking_target_type => "C",
116
+ :linking_target_id => id,
117
+ })
118
+ AssemblyGroup.all(options)
119
+ end
120
+ end
121
+ end