mercator_icecat 0.0.1 → 0.1

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +11 -0
  3. data/app/controllers/admin/metadata_controller.rb +14 -0
  4. data/app/models/mercator_icecat/access.rb +48 -0
  5. data/app/models/mercator_icecat/metadatum.rb +393 -0
  6. data/app/models/product_extensions.rb +28 -0
  7. data/app/views/layouts/mercator_icecat/application.html.erb +10 -11
  8. data/app/views/taglibs/admin/metadatum.dryml +117 -0
  9. data/config/routes.rb +4 -1
  10. data/db/migrate/20131219141435_create_toners.rb +42 -0
  11. data/db/migrate/20140411135444_change_icecat_metadata.rb +25 -0
  12. data/db/migrate/20140413123018_add_index_to_prod_id_in_icecat_metadata.rb +9 -0
  13. data/db/migrate/20140414141008_add_icacat_id_to_product_group.rb +9 -0
  14. data/db/migrate/20140415111836_add_icecat_id_to_property.rb +9 -0
  15. data/db/migrate/20140415112033_add_indices_for_icecat_id.rb +13 -0
  16. data/db/migrate/20140415122523_change_indices.rb +11 -0
  17. data/db/migrate/20140416065410_add_index_to_icecat_product_id.rb +15 -0
  18. data/lib/mercator_icecat/engine.rb +10 -1
  19. data/lib/mercator_icecat/version.rb +2 -2
  20. data/lib/string_extensions.rb +30 -0
  21. data/lib/tasks/mercator_icecat_tasks.rake +191 -4
  22. data/spec/controllers/mercator_icecat/metadata_controller_spec.rb +5 -0
  23. data/spec/factories/metadatum.rb +18 -0
  24. data/spec/models/mercator_icecat/metadatum_spec.rb +11 -0
  25. data/spec/models/product_spec.rb +5 -0
  26. metadata +79 -85
  27. data/app/helpers/mercator_icecat/application_helper.rb +0 -4
  28. data/test/dummy/README.rdoc +0 -28
  29. data/test/dummy/Rakefile +0 -6
  30. data/test/dummy/app/assets/javascripts/application.js +0 -13
  31. data/test/dummy/app/assets/stylesheets/application.css +0 -13
  32. data/test/dummy/app/controllers/application_controller.rb +0 -5
  33. data/test/dummy/app/helpers/application_helper.rb +0 -2
  34. data/test/dummy/app/views/layouts/application.html.erb +0 -14
  35. data/test/dummy/bin/bundle +0 -3
  36. data/test/dummy/bin/rails +0 -4
  37. data/test/dummy/bin/rake +0 -4
  38. data/test/dummy/config.ru +0 -4
  39. data/test/dummy/config/application.rb +0 -23
  40. data/test/dummy/config/boot.rb +0 -5
  41. data/test/dummy/config/database.yml +0 -25
  42. data/test/dummy/config/environment.rb +0 -5
  43. data/test/dummy/config/environments/development.rb +0 -29
  44. data/test/dummy/config/environments/production.rb +0 -80
  45. data/test/dummy/config/environments/test.rb +0 -36
  46. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  47. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  48. data/test/dummy/config/initializers/inflections.rb +0 -16
  49. data/test/dummy/config/initializers/mime_types.rb +0 -5
  50. data/test/dummy/config/initializers/secret_token.rb +0 -12
  51. data/test/dummy/config/initializers/session_store.rb +0 -3
  52. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  53. data/test/dummy/config/locales/en.yml +0 -23
  54. data/test/dummy/config/routes.rb +0 -4
  55. data/test/dummy/public/404.html +0 -58
  56. data/test/dummy/public/422.html +0 -58
  57. data/test/dummy/public/500.html +0 -57
  58. data/test/dummy/public/favicon.ico +0 -0
  59. data/test/integration/navigation_test.rb +0 -10
  60. data/test/mercator_icecat_test.rb +0 -7
  61. data/test/test_helper.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4deffa8cd6c702eed77bac34ab3017b702f0f854
4
- data.tar.gz: 867a87c65a178ec5f5967da1aaa15413364db81d
3
+ metadata.gz: 40286766b8ceba1e1c7b30b5212281e376266d76
4
+ data.tar.gz: 51c2ddba7064afe93b8d0cff1843966e0f5be042
5
5
  SHA512:
6
- metadata.gz: aad16e7b3a246dfb64929f46ed9bab73bde106491dbb144a2ab12e667121ee1f36624f47799ed7093cf7151a4e75e070dfb8d2f0181ed6ba534cd37430528fb6
7
- data.tar.gz: 5086e1e40dd3d7b8f0cf0ab89ae3b1f04368e95c93d11e6629ab6943ef1d616fc05ad63b97c52ffa5ce3b2c8c7223ec211805ef41a48cdcb76b8e45b169ab072
6
+ metadata.gz: 5305d1e84e0563e5f6a74948c62ecc00156381b3741a08663405fb5b3c2ffc61f5966f1a9a5276af2b08b9b188455dbc25fe61f6e788352dcd29099ddd179910
7
+ data.tar.gz: d8bcc01c56a69749d4aeb99d9ca5ea9dbae998ae7aae0e3357533f577c89bf75ede726d0bdb74e8bb0297cb138e824de6fe8851494f5ee34daf8bcd9decd2f23
@@ -3,3 +3,14 @@
3
3
  This engines provides Icecat Import for the Mercator Guided Selling Application.
4
4
 
5
5
  This project uses the GPL V3 license. See file LICENSE in the same directory for details about the GPL V3.
6
+
7
+ * Icecat Product: XY141ET corrupt Unicode Sequence
8
+
9
+ * A typical seqence for updating data would include the tasks:
10
+ bundle exec rake icecat:catalog:download_daily RAILS_ENV=production
11
+ bundle exec rake icecat:metadata:import_daily RAILS_ENV=production
12
+ bundle exec rake icecat:metadata:assign_products RAILS_ENV=production
13
+ bundle exec rake icecat:metadata:download_xml RAILS_ENV=production
14
+ bundle exec rake icecat:metadata:update_products RAILS_ENV=production
15
+ bundle exec rake icecat:metadata:update_product_relations RAILS_ENV=production
16
+ bundle exec rake icecat:metadata:import_missing_images RAILS_ENV=production
@@ -0,0 +1,14 @@
1
+ class Admin::MetadataController < Admin::AdminSiteController
2
+
3
+ def self.model
4
+ MercatorIcecat::Metadatum
5
+ end
6
+
7
+ def self.model_name
8
+ mercator_icecat_metadata
9
+ end
10
+
11
+ include Hobo::Controller::Model
12
+ hobo_model_controller
13
+ auto_actions :all
14
+ end
@@ -0,0 +1,48 @@
1
+ require 'open-uri'
2
+
3
+ module MercatorIcecat
4
+ class Access
5
+
6
+ attr_accessor(:user, :password, :vendor, :lang, :typ, :base_uri, :full_index_url, :daily_index_url, :open_uri_options)
7
+
8
+ USER = "donrudl"
9
+ PASSWORD = "cpP42J"
10
+ VENDOR = "HP"
11
+ LANG = "int"
12
+ TYP = "productxml"
13
+ BASE_URL = "http://data.icecat.biz"
14
+ FULL_INDEX_URL = BASE_URL + "/export/freexml/files.index.xml"
15
+ DAILY_INDEX_URL = BASE_URL + "/export/freexml/daily.index.xml"
16
+
17
+ # --- Class Methods --- #
18
+
19
+ def self.open_uri_options
20
+ {:http_basic_authentication => [self::USER, self::PASSWORD]}
21
+ end
22
+
23
+ def self.download_index(full: false)
24
+ if full
25
+ file = File.new(Rails.root.join("vendor","catalogs","files.index.xml"), "w")
26
+ io = open( FULL_INDEX_URL, open_uri_options.merge({"Accept-Encoding" => "gzip"}) )
27
+ else
28
+ file = File.new(Rails.root.join("vendor","catalogs",Date.today.to_s + "-index.xml"), "w")
29
+ io = open( DAILY_INDEX_URL, open_uri_options.merge({"Accept-Encoding" => "gzip"}) )
30
+ end
31
+ unzipped_io = Zlib::GzipReader.new( io )
32
+ unzipped_io.each do |line|
33
+ file.write line
34
+ end
35
+ file.close
36
+ io.close
37
+ end
38
+
39
+ def self.product(product_id: nil, path: nil) # accepts product_id or path as parameter
40
+ return open(self.product_url(product_id), open_uri_options).read if product_id
41
+ return open(BASE_URL + "/" + path, open_uri_options).read if path
42
+ end
43
+
44
+ def self.product_url(product_id: nil)
45
+ BASE_URL + "/xml_s3/xml_server3.cgi?prod_id=" + product_id + ";vendor=" + VENDOR + ";lang=" + LANG + ";output=" + TYP
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,393 @@
1
+ # encoding: utf-8
2
+
3
+ require 'saxerator'
4
+ require 'open-uri'
5
+ require 'string_extensions'
6
+
7
+ module MercatorIcecat
8
+ class Metadatum < ActiveRecord::Base
9
+
10
+ hobo_model # Don't put anything above this
11
+
12
+ fields do
13
+ path :string
14
+ icecat_updated_at :datetime
15
+ quality :string
16
+ supplier_id :string
17
+ icecat_product_id :string, :index => true
18
+ prod_id :string, :index => true
19
+ product_number :string
20
+ cat_id :string
21
+ on_market :string
22
+ model_name :string
23
+ product_view :string
24
+ timestamps
25
+ end
26
+ attr_accessible :path, :cat_id, :product_id, :icecat_updated_at, :quality, :supplier_id,
27
+ :prod_id, :on_market, :model_name, :product_view, :icecat_product_id
28
+
29
+ belongs_to :product, :class_name => "Product"
30
+
31
+ # --- Permissions --- #
32
+
33
+ def create_permitted?
34
+ acting_user.administrator?
35
+ end
36
+
37
+ def update_permitted?
38
+ acting_user.administrator?
39
+ end
40
+
41
+ def destroy_permitted?
42
+ acting_user.administrator?
43
+ end
44
+
45
+ def view_permitted?(field)
46
+ true
47
+ end
48
+
49
+ # --- Class Methods --- #
50
+
51
+ def self.import(full: false, date: Date.today)
52
+ if full
53
+ file = File.open(Rails.root.join("vendor","catalogs","files.index.xml"), "r")
54
+ else
55
+ file = File.open(Rails.root.join("vendor","catalogs",date.to_s + "-index.xml"), "r")
56
+ end
57
+
58
+ parser = Saxerator.parser(file) do |config|
59
+ config.put_attributes_in_hash!
60
+ end
61
+
62
+ # Hewlett Packard has Supplier_id = 1
63
+ parser.for_tag("file").with_attribute("Supplier_id", "1").each do |product|
64
+ metadatum = self.find_or_create_by_icecat_product_id(product["Product_ID"])
65
+ mode = Time.now - metadatum.created_at > 5 ? " updated." : " created."
66
+
67
+ model_name = product["Model_Name"].fix_utf8 if product["Model_Name"].present?
68
+
69
+ if metadatum.update(path: product["path"],
70
+ cat_id: product["Catid"],
71
+ icecat_product_id: product["Product_ID"],
72
+ icecat_updated_at: product["Updated"],
73
+ quality: product["Quality"],
74
+ supplier_id: product["Supplier_id"],
75
+ prod_id: product["Prod_ID"],
76
+ on_market: product["On_Market"],
77
+ model_name: model_name,
78
+ product_view: product["Product_View"])
79
+ ::JobLogger.info("Metadatum " + product["Prod_ID"].to_s + mode)
80
+ else
81
+ ::JobLogger.error("Metadatum " + product["Prod_ID"].to_s + " could not be saved: " + metadatum.errors.first )
82
+ end
83
+ end
84
+ file.close
85
+ end
86
+
87
+ def self.assign_products(only_missing: true)
88
+ if only_missing
89
+ products = Product.without_icecat_metadata
90
+ ::JobLogger.warn(products.count.to_s + " products without metadata.")
91
+ else
92
+ products = Product.all
93
+ end
94
+
95
+ products.each do |product|
96
+ metadata = self.where(prod_id: product.icecat_article_number)
97
+ amount = metadata.count
98
+ metadata.each_with_index do |metadatum, index|
99
+ if metadatum.update(product_id: product.id)
100
+ ::JobLogger.info("Product " + product.number.to_s + " assigned to " + metadatum.id.to_s + " (" + index.to_s + "/" + amount.to_s + ")")
101
+ else
102
+ ::JobLogger.error("Product " + product.number.to_s + " assigned to " + metadatum.id.to_s)
103
+ end
104
+ end
105
+ end
106
+
107
+ products = Product.without_icecat_metadata
108
+ ::JobLogger.warn(products.count.to_s + " products without metadata.")
109
+ end
110
+
111
+ def self.download(overwrite: false, from_today: true)
112
+ if from_today
113
+ @twentyfivehours = Time.now - 25.hours
114
+ metadata = self.where{ (product_id != nil) & (updated_at > my{@twentyfivehours})}
115
+ else
116
+ metadata = self.where{ product_id != nil }
117
+ end
118
+
119
+ amount = metadata.count
120
+ metadata.each_with_index do |metadatum, index|
121
+ if metadatum.download(overwrite: overwrite)
122
+ ::JobLogger.info("XML Metadatum " + metadatum.prod_id.to_s + " downloaded. (" + index.to_s + "/" + amount.to_s + ")")
123
+ else
124
+ ::JobLogger.info("XML Metadatum " + metadatum.prod_id.to_s + " exists (no overwrite)!")
125
+ end
126
+ end
127
+ end
128
+
129
+ def self.update_products(from_today: true)
130
+ if from_today
131
+ @twentyfivehours = Time.now - 25.hours
132
+ metadata = self.where{ (product_id != nil) & (updated_at > my{@twentyfivehours})}.order(id: :asc)
133
+ else
134
+ metadata = self.where{ product_id != nil }.order(id: :asc)
135
+ end
136
+
137
+ amount = metadata.count
138
+ metadata.each_with_index do |metadatum, index|
139
+ # if-clause is handy for resume after dump
140
+ metadatum.update_product # if metadatum.id >= 109279
141
+ ::JobLogger.info("(" + index.to_s + "/" + amount.to_s + ")")
142
+ end
143
+ end
144
+
145
+ def self.update_product_relations(from_today: true)
146
+ if from_today
147
+ @twentyfivehours = Time.now - 25.hours
148
+ metadata = self.where{ (product_id != nil) & (updated_at > my{@twentyfivehours})}.order(id: :asc)
149
+ else
150
+ metadata = self.where{ product_id != nil }.order(id: :asc)
151
+ end
152
+
153
+ amount = metadata.count
154
+ metadata.each_with_index do |metadatum, index|
155
+ metadatum.update_product_relations
156
+ ::JobLogger.info("(" + index.to_s + "/" + amount.to_s + ")")
157
+ end
158
+ end
159
+
160
+ def self.import_missing_images
161
+ metadata = self.includes(:product).where{product.id != nil}
162
+ .where{product.photo_file_name == nil}.references(:product).order(id: :asc)
163
+ metadata.each do |metadatum|
164
+ metadatum.import_missing_image
165
+ end
166
+ end
167
+
168
+
169
+ # --- Instance Methods --- #
170
+
171
+ def download(overwrite: false)
172
+ unless overwrite
173
+ return false if File.exist?(Rails.root.join("vendor","xml",icecat_product_id.to_s + ".xml"))
174
+ end
175
+
176
+ unless self.path
177
+ return false
178
+ end
179
+
180
+ # force_encoding fixes: Encoding::UndefinedConversionError: "\xC3" from ASCII-8BIT to UTF-8
181
+ begin
182
+ io = open(Access::BASE_URL + "/" + self.path, Access.open_uri_options).read.force_encoding('UTF-8')
183
+ file = File.new(Rails.root.join("vendor","xml",icecat_product_id.to_s + ".xml"), "w")
184
+ io.each_line do |line|
185
+ file.write line
186
+ end
187
+
188
+ file.close
189
+ return true
190
+ rescue
191
+ ::JobLogger.error("Download error: " + Access::BASE_URL + "/" + self.path)
192
+ return false
193
+ end
194
+ end
195
+
196
+ def update_product
197
+ # :en => lang_id = 1, :de => lang_id = 4
198
+ file = open(Rails.root.join("vendor","xml",icecat_product_id.to_s + ".xml")).read
199
+ product_nodeset = Nokogiri::XML(file).xpath("//ICECAT-interface/Product")[0]
200
+ product = self.product
201
+
202
+ description_de = try_to { product_nodeset.xpath("ProductDescription[@langid='4']")[0]["ShortDesc"].fix_utf8 }
203
+ description_en = try_to { product_nodeset.xpath("ProductDescription[@langid='1']")[0]["ShortDesc"].fix_utf8 }
204
+ long_description_de = try_to { product_nodeset.xpath("ProductDescription[@langid='4']")[0]["LongDesc"].fix_utf8 }
205
+ long_description_en = try_to { product_nodeset.xpath("ProductDescription[@langid='1']")[0]["LongDesc"].fix_utf8 }
206
+ warranty_de = try_to { product_nodeset.xpath("ProductDescription[@langid='4']")[0]["WarrantyInfo"].fix_utf8 }
207
+ warranty_en = try_to { product_nodeset.xpath("ProductDescription[@langid='1']")[0]["WarrantyInfo"].fix_utf8 }
208
+
209
+ product.update(# title_de: product_nodeset["Title"],
210
+ # title_en: product_nodeset["Title"],
211
+ description_de: description_de,
212
+ description_en: description_en,
213
+ long_description_de: long_description_de,
214
+ long_description_en: long_description_en,
215
+ warranty_de: warranty_de,
216
+ warranty_en: warranty_en)
217
+
218
+ property_groups_nodeset = product_nodeset.xpath("CategoryFeatureGroup")
219
+ property_groups_nodeset.each do |property_group_nodeset|
220
+ icecat_id = property_group_nodeset["ID"]
221
+ name_en = try_to { property_group_nodeset.xpath("FeatureGroup/Name[@langid='1']")[0]["Value"].fix_utf8 }
222
+ name_de = try_to { property_group_nodeset.xpath("FeatureGroup/Name[@langid='4']")[0]["Value"].fix_utf8 }
223
+ name_de ||= name_en # English, if German not available
224
+ name_de ||= try_to { property_group_nodeset.xpath("FeatureGroup/Name")[0]["Value"].fix_utf8 }
225
+ # anything if neither German nor English available
226
+
227
+ property_group = ::PropertyGroup.find_by_icecat_id(icecat_id)
228
+ unless property_group
229
+ property_group = ::PropertyGroup.new(icecat_id: icecat_id,
230
+ name_de: name_de,
231
+ name_en: name_en,
232
+ position: icecat_id) # no better idea ...
233
+ if property_group.save
234
+ ::JobLogger.info("PropertyGroup " + icecat_id.to_s + " created.")
235
+ else
236
+ ::JobLogger.error("PropertyGroup " + icecat_id.to_s + " could not be created: " + property_group.errors.first.to_s)
237
+ end
238
+ end
239
+ end
240
+
241
+ product.values.destroy_all
242
+
243
+ features_nodeset = product_nodeset.xpath("ProductFeature")
244
+ features_nodeset.each do |feature|
245
+ # icecat_presentation_value = feature.xpath("Presentation_Value") # not used here
246
+ icecat_feature_id = feature.xpath("Feature")[0]["ID"].to_i
247
+ icecat_value = feature["Value"]
248
+ icecat_feature_group_id = feature["CategoryFeatureGroup_ID"]
249
+
250
+ name_en = try_to { feature.xpath("Feature/Name[@langid='1']")[0]["Value"].fix_utf8 }
251
+ name_de = try_to { feature.xpath("Feature/Name[@langid='4']")[0]["Value"].fix_utf8 }
252
+ name_de ||= name_en # English, if German not available
253
+ name_de ||= try_to { feature.xpath("Feature/Name")[0]["Value"].fix_utf8 } # anything if neither German nor English available
254
+
255
+ unit_en = try_to { feature.xpath("Feature/Measure/Signs/Sign[@langid='1']")[0].content.fix_utf8 }
256
+ unit_de = try_to { feature.xpath("Feature/Measure/Signs/Sign[@langid='4']")[0].content.fix_utf8 }
257
+ unit_de ||= unit_en # English, if German not available
258
+ unit_de ||= try_to { feature.xpath("Feature/Measure/Signs/Sign")[0].content.fix_utf8 }
259
+ # anything if neither German nor English available
260
+
261
+ property_group = PropertyGroup.find_by_icecat_id(icecat_feature_group_id)
262
+
263
+ property = Property.where(icecat_id: icecat_feature_id).first
264
+ unless property
265
+ property = Property.new(icecat_id: icecat_feature_id,
266
+ position: icecat_feature_id,
267
+ name_de: name_de,
268
+ name_en: name_en,
269
+ datatype: icecat_value.icecat_datatype)
270
+ if property.save
271
+ ::JobLogger.info("Property " + property.id.to_s + " saved.")
272
+ else
273
+ ::JobLogger.error("Property could not be saved:" + property.errors.first.to_s)
274
+ end
275
+ end
276
+
277
+ value = Value.where(property_group_id: property_group.id, property_id: property.id,
278
+ product_id: product.id, state: icecat_value.icecat_datatype).first
279
+ unless value
280
+ value = Value.new(property_group_id: property_group.id, property_id: property.id, product_id: product.id)
281
+ value.state = icecat_value.icecat_datatype
282
+ end
283
+
284
+ if icecat_value.icecat_datatype == "flag"
285
+ value.flag = ( icecat_value == "Y" )
286
+ end
287
+
288
+ if icecat_value.icecat_datatype == "numeric"
289
+ value.amount = icecat_value.to_f
290
+ value.unit_de = try_to { unit_de.fix_utf8 }
291
+ value.unit_en = try_to { unit_en.fix_utf8 }
292
+ end
293
+
294
+ if icecat_value.icecat_datatype == "textual"
295
+ value.title_de = try_to { icecat_value.truncate(252).fix_utf8 }
296
+ value.title_en = try_to { icecat_value.truncate(252).fix_utf8 }
297
+ value.unit_de = try_to { unit_de.fix_utf8 }
298
+ value.unit_en = try_to { unit_en.fix_utf8 }
299
+ end
300
+
301
+ if value.save
302
+ ::JobLogger.info("Value " + value.id.to_s + " saved.")
303
+ else
304
+ ::JobLogger.error("Value could not be saved:" + value.errors.first)
305
+ end
306
+ end
307
+ ::JobLogger.info("=== Metadatum " + id.to_s + " updated Product " + product_id.to_s + " ===")
308
+ end
309
+
310
+ def delete_relations
311
+ product = self.product
312
+ relations_count = product.productrelations.count
313
+ product.productrelations.destroy_all
314
+ supplies_count = product.supplyrelations.count
315
+ product.supplyrelations.destroy_all
316
+ ::JobLogger.info(relations_count.to_s + " Productrel., " +
317
+ supplies_count.to_s + " Supplyrel. deleted for Product " + product.id.to_s +
318
+ " Metadatum " + self.id.to_s)
319
+ end
320
+
321
+ def update_product_relations
322
+ file = open(Rails.root.join("vendor","xml",icecat_product_id.to_s + ".xml")).read
323
+ product_nodeset = Nokogiri::XML(file).xpath("//ICECAT-interface/Product")[0]
324
+ product = self.product
325
+ cat_id = self.cat_id
326
+
327
+ self.delete_relations
328
+
329
+ unknown_products = 0
330
+ icecat_ids = []
331
+ product_nodeset.xpath("ProductRelated").each do |relation|
332
+ icecat_ids << try_to { relation.xpath("Product")[0]["ID"].to_i }
333
+ end
334
+
335
+ related_metadata = Metadatum.where(icecat_product_id: icecat_ids)
336
+ related_metadata.each do |related_metadatum|
337
+ related_product_id = try_to { related_metadatum.product_id.to_i }
338
+
339
+ if related_product_id > 0
340
+ if related_metadatum.cat_id == cat_id
341
+ product.productrelations.new(related_product_id: related_product_id)
342
+ else
343
+ product.supplyrelations.new(supply_id: related_product_id)
344
+ end
345
+ else
346
+ unknown_products += 1
347
+ end
348
+ end
349
+
350
+ if product.save(validate: false) # FIXME!: This time without validations ...
351
+ ::JobLogger.info("Product " + product.id.to_s + ": " +
352
+ product.productrelations.count.to_s + " Productrel. " +
353
+ product.supplyrelations.count.to_s + ", Supplyrel. created, " +
354
+ unknown_products.to_s + " unknown.")
355
+ else
356
+ ::JobLogger.error("Product " + product.id.to_s + " could not be updated")
357
+ end
358
+ end
359
+
360
+ def import_missing_image
361
+ file = open(Rails.root.join("vendor","xml",icecat_product_id.to_s + ".xml")).read
362
+ product_nodeset = Nokogiri::XML(file).xpath("//ICECAT-interface/Product")[0]
363
+
364
+ product = self.product
365
+ return nil if product.photo_file_name # no overwriting intended
366
+
367
+ path = product_nodeset["HighPic"]
368
+
369
+ if path.empty?
370
+ ::JobLogger.warn("no Image available for Product " + product.id.to_s)
371
+ return nil # no image available
372
+ end
373
+
374
+ begin
375
+ io = StringIO.new(open(path, Access.open_uri_options).read)
376
+ io.class.class_eval { attr_accessor :original_filename }
377
+ io.original_filename = path.split("/").last
378
+
379
+ product.photo = io
380
+
381
+ if product.save(validate: false) # FIXME!: This time without validations ...
382
+ ::JobLogger.info("Image " + path.split("/").last + " for Product " + product.id.to_s + " saved." )
383
+ else
384
+ ::JobLogger.error("Image " + path.split("/").last + " for Product " + product.id.to_s + " could not be saved!" )
385
+ end
386
+ rescue Exception => e
387
+ ::JobLogger.warn("Image " + path + " could not be loaded!" )
388
+ ::JobLogger.warn(e)
389
+ end
390
+ end
391
+
392
+ end
393
+ end