mercator_icecat 0.0.1 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
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