caboose-rets 0.1.151 → 0.1.152

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.
@@ -1,625 +0,0 @@
1
- #require 'ruby-rets'
2
- require "rets/version"
3
- require "rets/exceptions"
4
- require "rets/client"
5
- require "rets/http"
6
- require "rets/stream_http"
7
- require "rets/base/core"
8
- require "rets/base/sax_search"
9
- require "rets/base/sax_metadata"
10
-
11
- require 'httparty'
12
- require 'json'
13
-
14
- # http://rets.solidearth.com/ClientHome.aspx
15
-
16
- class CabooseRets::RetsImporter # < ActiveRecord::Base
17
-
18
- @@rets_client = nil
19
- @@config = nil
20
-
21
- def self.config
22
- return @@config
23
- end
24
-
25
- def self.get_config
26
- @@config = {
27
- 'url' => nil, # URL to the RETS login
28
- 'username' => nil,
29
- 'password' => nil,
30
- 'temp_path' => nil,
31
- 'log_file' => nil,
32
- 'media_base_url' => nil
33
- }
34
- config = YAML::load(File.open("#{Rails.root}/config/rets_importer.yml"))
35
- config = config[Rails.env]
36
- config.each { |key,val| @@config[key] = val }
37
- end
38
-
39
- def self.client
40
- self.get_config if @@config.nil? || @@config['url'].nil?
41
-
42
- if @@rets_client.nil?
43
- @@rets_client = RETS::Client.login(
44
- :url => 'http://rets.wamls.mlsmatrix.com/rets/Login.ashx', #@@config['url'],
45
- :username => 'RETS_6', #@@config['username'],
46
- :password => 'ellis' #@@config['password']
47
- )
48
- end
49
- return @@rets_client
50
- end
51
-
52
- def self.meta(class_type)
53
- Caboose::StdClass.new({ :search_type => 'Property' , :remote_key_field => 'MLS' , :local_key_field => 'mls' , :local_table => 'rets_properties' , :date_modified_field => 'DATE_MODIFIED'})
54
- # case class_type
55
- # when 'RES' then Caboose::StdClass.new({ :search_type => 'Property' , :remote_key_field => 'MLS' , :local_key_field => 'mls' , :local_table => 'rets_properties' , :date_modified_field => 'DATE_MODIFIED' })
56
- # when 'OFF' then Caboose::StdClass.new({ :search_type => 'Office' , :remote_key_field => 'LO_LO_CODE' , :local_key_field => 'lo_code' , :local_table => 'rets_offices' , :date_modified_field => 'LO_DATE_MODIFIED' })
57
- # when 'AGT' then Caboose::StdClass.new({ :search_type => 'Agent' , :remote_key_field => 'LA_LA_CODE' , :local_key_field => 'la_code' , :local_table => 'rets_agents' , :date_modified_field => 'LA_DATE_MODIFIED' })
58
- # when 'OPH' then Caboose::StdClass.new({ :search_type => 'OpenHouse' , :remote_key_field => 'ID' , :local_key_field => 'id' , :local_table => 'rets_open_houses' , :date_modified_field => 'DATE_MODIFIED' })
59
- # when 'GFX' then Caboose::StdClass.new({ :search_type => 'Media' , :remote_key_field => 'MEDIA_ID' , :local_key_field => 'media_id' , :local_table => 'rets_media' , :date_modified_field => 'DATE_MODIFIED' })
60
- # end
61
- end
62
-
63
- #=============================================================================
64
- # Import method
65
- #=============================================================================
66
-
67
- def self.import(class_type, query)
68
- m = self.meta(class_type)
69
- #self.log("Importing #{m.search_type}:#{class_type} with query #{query}...")
70
- self.get_config if @@config.nil? || @@config['url'].nil?
71
- params = {
72
- :search_type => m.search_type,
73
- :class => class_type,
74
- :query => query,
75
- :limit => -1,
76
- :timeout => -1
77
- }
78
- obj = nil
79
- begin
80
- self.client.search(params) do |data|
81
- obj = self.get_instance_with_id(class_type, data)
82
- if obj.nil?
83
- self.log("Error: object is nil")
84
- self.log(data.inspect)
85
- next
86
- end
87
- obj.parse(data)
88
- obj.save
89
- end
90
- rescue RETS::HTTPError => err
91
- self.log "Import error for #{class_type}: #{query}"
92
- self.log err.message
93
- end
94
-
95
- end
96
-
97
- def self.get_instance_with_id(class_type, data)
98
- obj = nil
99
- m = CabooseRets::Property
100
- # m = case class_type
101
- # when 'OPH' then CabooseRets::OpenHouse
102
- # when 'GFX' then CabooseRets::Media
103
- # when 'COM' then CabooseRets::CommercialProperty
104
- # when 'LND' then CabooseRets::LandProperty
105
- # when 'MUL' then CabooseRets::MultiFamilyProperty
106
- # when 'RES' then CabooseRets::ResidentialProperty
107
- # when 'AGT' then CabooseRets::Agent
108
- # when 'OFF' then CabooseRets::Office
109
- # end
110
- obj = m.where(:id => data['ID'].to_i).exists? ? m.where(:id => data['ID'].to_i).first : m.new(:id=> data['ID'].to_i)
111
- # obj = case class_type
112
- # when 'OPH' then m.where(:id => data['ID'].to_i ).exists? ? m.where(:id => data['ID'].to_i ).first : m.new(:id => data['ID'].to_i )
113
- # when 'GFX' then m.where(:media_id => data['MEDIA_ID'] ).exists? ? m.where(:media_id => data['MEDIA_ID'] ).first : m.new(:media_id => data['MEDIA_ID'] )
114
- # when 'COM' then m.where(:id => data['MLS'].to_i ).exists? ? m.where(:id => data['MLS'].to_i ).first : m.new(:id => data['MLS'].to_i )
115
- # when 'LND' then m.where(:id => data['MLS'].to_i ).exists? ? m.where(:id => data['MLS'].to_i ).first : m.new(:id => data['MLS'].to_i )
116
- # when 'MUL' then m.where(:id => data['MLS'].to_i ).exists? ? m.where(:id => data['MLS'].to_i ).first : m.new(:id => data['MLS'].to_i )
117
- # when 'RES' then m.where(:id => data['MLS'].to_i ).exists? ? m.where(:id => data['MLS'].to_i ).first : m.new(:id => data['MLS'].to_i )
118
- # when 'AGT' then m.where(:la_code => data['LA_LA_CODE'] ).exists? ? m.where(:la_code => data['LA_LA_CODE'] ).first : m.new(:la_code => data['LA_LA_CODE'] )
119
- # when 'OFF' then m.where(:lo_code => data['LO_LO_CODE'] ).exists? ? m.where(:lo_code => data['LO_LO_CODE'] ).first : m.new(:lo_code => data['LO_LO_CODE'] )
120
- # end
121
- return obj
122
- end
123
-
124
- #=============================================================================
125
- # Main updater
126
- #=============================================================================
127
-
128
- def self.update_after(date_modified, save_images = true)
129
- self.delay(:priority => 10, :queue => 'rets').update_helper('PRO', date_modified, save_images)
130
- # self.delay(:queue => 'rets').update_helper('RES', date_modified, save_images)
131
- # self.delay(:queue => 'rets').update_helper('COM', date_modified, save_images)
132
- # self.delay(:queue => 'rets').update_helper('LND', date_modified, save_images)
133
- # self.delay(:queue => 'rets').update_helper('MUL', date_modified, save_images)
134
- # self.delay(:queue => 'rets').update_helper('OFF', date_modified, save_images)
135
- # self.delay(:queue => 'rets').update_helper('AGT', date_modified, save_images)
136
- # self.delay(:queue => 'rets').update_helper('OPH', date_modified, save_images)
137
- end
138
-
139
- def self.update_helper(class_type, date_modified, save_images = true)
140
- m = self.meta(class_type)
141
- k = m.remote_key_field
142
- d = date_modified.in_time_zone(CabooseRets::timezone).strftime("%FT%T")
143
- params = {
144
- :search_type => m.search_type,
145
- :class => class_type,
146
- :select => [m.remote_key_field],
147
- :query => "(#{m.date_modified_field}=#{d}+)",
148
- :standard_names_only => true,
149
- :timeout => -1
150
- }
151
- self.client.search(params) do |data|
152
- self.delay(:priority => 10, :queue => 'rets').import_properties( data[k], save_images)
153
- # case class_type
154
- # when 'RES' then self.delay(:priority => 10, :queue => 'rets').import_residential_property( data[k], save_images)
155
- # when 'COM' then self.delay(:priority => 10, :queue => 'rets').import_commercial_property( data[k], save_images)
156
- # when 'LND' then self.delay(:priority => 10, :queue => 'rets').import_land_property( data[k], save_images)
157
- # when 'MUL' then self.delay(:priority => 10, :queue => 'rets').import_multi_family_property( data[k], save_images)
158
- # when 'OFF' then self.delay(:priority => 10, :queue => 'rets').import_office( data[k], save_images)
159
- # when 'AGT' then self.delay(:priority => 10, :queue => 'rets').import_agent( data[k], save_images)
160
- # when 'OPH' then self.delay(:priority => 10, :queue => 'rets').import_open_house( data[k], save_images)
161
- # end
162
- end
163
- end
164
-
165
- #=============================================================================
166
- # Single model import methods (called from a worker dyno)
167
- #=============================================================================
168
-
169
- def self.import_property(mls, save_images = true)
170
- self.import('RES', "(MLS=*#{mls}*)")
171
- p = CabooseRets::Property.where(:id => mls.to_i).first
172
- # p = CabooseRets::ResidentialProperty.where(:id => mls.to_i).first
173
- # if p.nil?
174
- # self.import('COM', "(MLS=*#{mls}*)")
175
- # p = CabooseRets::CommercialProperty.where(:id => mls.to_i).first
176
- # if p.nil?
177
- # self.import('LND', "(MLS=*#{mls}*)")
178
- # p = CabooseRets::LandProperty.where(:id => mls.to_i).first
179
- # if p.nil?
180
- # self.import('MUL', "(MLS=*#{mls}*)")
181
- # p = CabooseRets::MultiFamilyProperty.where(:id => mls.to_i).first
182
- # return if p.nil?
183
- # end
184
- # end
185
- # end
186
- self.download_property_images(p, save_images)
187
- end
188
-
189
- def self.import_properties(mls, save_images = true)
190
- self.import('PRO', "(MLS=*#{mls}*)")
191
- p = CabooseRets::Property.where(:id => mls.to_i).first
192
- self.download_property_images(p, save_images)
193
- self.update_coords(p)
194
- end
195
-
196
- # def self.import_residential_property(mls, save_images = true)
197
- # self.import('RES', "(MLS=*#{mls}*)")
198
- # p = CabooseRets::ResidentialProperty.where(:id => mls.to_i).first
199
- # self.download_property_images(p, save_images)
200
- # self.update_coords(p)
201
- # end
202
- #
203
- # def self.import_commercial_property(mls, save_images = true)
204
- # self.import('COM', "(MLS=*#{mls}*)")
205
- # p = CabooseRets::CommercialProperty.where(:id => mls.to_i).first
206
- # self.download_property_images(p, save_images)
207
- # self.update_coords(p)
208
- # end
209
- #
210
- # def self.import_land_property(mls, save_images = true)
211
- # self.import('LND', "(MLS=*#{mls}*)")
212
- # p = CabooseRets::LandProperty.where(:id => mls.to_i).first
213
- # self.download_property_images(p, save_images)
214
- # self.update_coords(p)
215
- # end
216
- #
217
- # def self.import_multi_family_property(mls, save_images = true)
218
- # self.import('MUL', "(MLS=*#{mls}*)")
219
- # p = CabooseRets::MultiFamilyProperty.where(:id => mls.to_i).first
220
- # self.download_property_images(p, save_images)
221
- # self.update_coords(p)
222
- # end
223
- #
224
- # def self.import_office(lo_code, save_images = true)
225
- # self.import('OFF', "(LO_LO_CODE=*#{lo_code}*)")
226
- # office = CabooseRets::Office.where(:lo_code => lo_code.to_s).first
227
- # self.download_office_image(office) if save_images == true
228
- # end
229
- #
230
- # def self.import_agent(la_code, save_images = true)
231
- # self.import('AGT', "(LA_LA_CODE=*#{la_code}*)")
232
- # a = CabooseRets::Agent.where(:la_code => la_code.to_s).first
233
- # self.download_agent_image(a) #if save_images == true
234
- # end
235
- #
236
- # def self.import_open_house(id, save_images = true)
237
- # self.import('OPH', "((ID=#{id}+),(ID=#{id}-))")
238
- # end
239
-
240
- def self.import_media(id, save_images = true)
241
- self.import('GFX', "((MEDIA_ID=#{id}+),(MEDIA_ID=#{id}-))")
242
- end
243
-
244
- #=============================================================================
245
- # Images
246
- #=============================================================================
247
-
248
- def self.download_property_images(p, save_images = true)
249
- return if save_images == false
250
-
251
- self.log("- Downloading GFX records for #{p.mls}...")
252
- params = {
253
- :search_type => 'Media',
254
- :class => 'GFX',
255
- :query => "(MLS=*#{p.mls}*)",
256
- :timeout => -1
257
- }
258
- ids = []
259
- self.client.search(params) do |data|
260
- ids << data['MEDIA_ID']
261
- m = CabooseRets::Media.where(:media_id => data['MEDIA_ID']).first
262
- m = CabooseRets::Media.new if m.nil?
263
- m.parse(data)
264
- m.save
265
- end
266
-
267
- if ids.count > 0
268
- # Delete any records in the local database that shouldn't be there
269
- self.log("- Deleting GFX records for MLS ##{p.mls} in the local database that are not in the remote database...")
270
- query = "select media_id from rets_media where mls = '#{p.mls}'"
271
- rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
272
- local_ids = rows.collect{ |row| row['media_id'] }
273
- ids_to_remove = local_ids - ids
274
- if ids_to_remove && ids_to_remove.count > 0
275
- query = ["delete from rets_media where media_id in (?)", ids_to_remove]
276
- ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
277
- end
278
- end
279
-
280
- end
281
-
282
- def self.download_agent_image(agent)
283
- self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
284
- begin
285
- self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => agent.la_code) do |headers, content|
286
- agent.verify_meta_exists
287
- agent.meta.image_location = headers['location']
288
- agent.meta.save
289
- end
290
- rescue RETS::APIError => err
291
- self.log "No image for #{agent.first_name} #{agent.last_name}."
292
- self.log err
293
- end
294
- end
295
-
296
- def self.download_office_image(office)
297
- #self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
298
- #begin
299
- # self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => agent.la_code) do |headers, content|
300
- # agent.verify_meta_exists
301
- # agent.meta.image_location = headers['location']
302
- # agent.meta.save
303
- # end
304
- #rescue RETS::APIError => err
305
- # self.log "No image for #{agent.first_name} #{agent.last_name}."
306
- # self.log err
307
- #end
308
- end
309
-
310
- #=============================================================================
311
- # GPS
312
- #=============================================================================
313
-
314
- def self.update_coords(p = nil)
315
- if p.nil?
316
- models = CabooseRets::Property #[CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty]
317
- names = ["commercial", "land", "multi-family", "residential"]
318
- i = 0
319
- models.each do |model|
320
- self.log "Updating coords #{names[i]} properties..."
321
- model.where(:latitude => nil).reorder(:mls).each do |p|
322
- self.delay(:priority => 10, :queue => 'rets').update_coords(p)
323
- end
324
- i = i + 1
325
- end
326
- return
327
- end
328
-
329
- self.log "Getting coords for mls #{p.mls}..."
330
- coords = self.coords_from_address(CGI::escape "#{p.street_num} #{p.street_name}, #{p.city}, #{p.state} #{p.zip}")
331
- if coords.nil? || coords == false
332
- self.log "Can't set coords for mls acct #{p.mls}..."
333
- return
334
- end
335
-
336
- p.latitude = coords['lat']
337
- p.longitude = coords['lng']
338
- p.save
339
- end
340
-
341
- def self.coords_from_address(address)
342
- #return false
343
- begin
344
- uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
345
- uri.gsub!(" ", "+")
346
- resp = HTTParty.get(uri)
347
- json = JSON.parse(resp.body)
348
- return json['results'][0]['geometry']['location']
349
- rescue
350
- self.log "Error: #{uri}"
351
- sleep(2)
352
- return false
353
- end
354
- end
355
-
356
- #=============================================================================
357
- # Purging
358
- #=============================================================================
359
-
360
- def self.purge
361
- self.purge_properties
362
- self.purge_residential
363
- self.purge_commercial
364
- self.purge_land
365
- self.purge_multi_family
366
- self.purge_offices
367
- #self.purge_agents
368
- self.purge_open_houses
369
- self.purge_media
370
- end
371
-
372
- def self.purge_properties() self.delay(:priority => 10, :queue => 'rets').purge_helper('PRO', '2012-01-01') end
373
- def self.purge_residential() self.delay(:priority => 10, :queue => 'rets').purge_helper('RES', '2012-01-01') end
374
- def self.purge_commercial() self.delay(:priority => 10, :queue => 'rets').purge_helper('COM', '2012-01-01') end
375
- def self.purge_land() self.delay(:priority => 10, :queue => 'rets').purge_helper('LND', '2012-01-01') end
376
- def self.purge_multi_family() self.delay(:priority => 10, :queue => 'rets').purge_helper('MUL', '2012-01-01') end
377
- def self.purge_offices() self.delay(:priority => 10, :queue => 'rets').purge_helper('OFF', '2012-01-01') end
378
- def self.purge_agents() self.delay(:priority => 10, :queue => 'rets').purge_helper('AGT', '2012-01-01') end
379
- def self.purge_open_houses() self.delay(:priority => 10, :queue => 'rets').purge_helper('OPH', '2012-01-01') end
380
- def self.purge_media() self.delay(:priority => 10, :queue => 'rets').purge_helper('GFX', '2012-01-01') end
381
-
382
- def self.purge_helper(class_type, date_modified)
383
- m = self.meta(class_type)
384
-
385
- self.log("Purging #{class_type}...")
386
-
387
- # Get the total number of records
388
- self.log("- Getting total number of records for #{class_type}...")
389
- params = {
390
- :search_type => m.search_type,
391
- :class => class_type,
392
- :query => "(#{m.date_modified_field}=#{date_modified}T00:00:01+)",
393
- :standard_names_only => true,
394
- :timeout => -1
395
- }
396
- self.client.search(params.merge({ :count_mode => :only }))
397
- count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
398
- batch_count = (count.to_f/5000.0).ceil
399
-
400
- ids = []
401
- k = m.remote_key_field
402
- (0...batch_count).each do |i|
403
- self.log("- Getting ids for #{class_type} (batch #{i+1} of #{batch_count})...")
404
- self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
405
- ids << (class_type == 'OPH' ? data[k].to_i : data[k])
406
- end
407
- end
408
-
409
- # Only do stuff if we got a real response from the server
410
- if ids.count > 0
411
-
412
- # Delete any records in the local database that shouldn't be there
413
- self.log("- Finding #{class_type} records in the local database that are not in the remote database...")
414
- t = m.local_table
415
- k = m.local_key_field
416
- query = "select distinct #{k} from #{t}"
417
- rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
418
- local_ids = rows.collect{ |row| row[k] }
419
- ids_to_remove = local_ids - ids
420
- self.log("- Found #{ids_to_remove.count} #{class_type} records in the local database that are not in the remote database.")
421
- self.log("- Deleting #{class_type} records in the local database that shouldn't be there...")
422
- query = ["delete from #{t} where #{k} in (?)", ids_to_remove]
423
- ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
424
-
425
- # Find any ids in the remote database that should be in the local database
426
- self.log("- Finding #{class_type} records in the remote database that should be in the local database...")
427
- query = "select distinct #{k} from #{t}"
428
- rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
429
- local_ids = rows.collect{ |row| row[k] }
430
- ids_to_add = ids - local_ids
431
- ids_to_add = ids_to_add.sort.reverse
432
- self.log("- Found #{ids_to_add.count} #{class_type} records in the remote database that we need to add to the local database.")
433
- ids_to_add.each do |id|
434
- self.log("- Importing #{id}...")
435
- self.delay(:priority => 10, :queue => 'rets').import_properties(id, false)
436
- # case class_type
437
- # when 'RES' then self.delay(:queue => 'rets').import_residential_property(id, false)
438
- # when 'COM' then self.delay(:queue => 'rets').import_commercial_property(id, false)
439
- # when 'LND' then self.delay(:queue => 'rets').import_land_property(id, false)
440
- # when 'MUL' then self.delay(:queue => 'rets').import_multi_family_property(id, false)
441
- # when 'OFF' then self.delay(:queue => 'rets').import_office(id, false)
442
- # when 'AGT' then self.delay(:queue => 'rets').import_agent(id, false)
443
- # when 'OPH' then self.delay(:queue => 'rets').import_open_house(id, false)
444
- # when 'GFX' then self.delay(:queue => 'rets').import_media(id, false)
445
- # end
446
- end
447
-
448
- end
449
-
450
- end
451
-
452
- def self.get_media_urls
453
- m = self.meta(class_type)
454
-
455
- # Get the total number of records
456
- params = {
457
- :search_type => m.search_type,
458
- :class => class_type,
459
- :query => "(#{m.date_modified_field}=#{date_modified}T00:00:01+)",
460
- :standard_names_only => true,
461
- :timeout => -1
462
- }
463
- self.client.search(params.merge({ :count_mode => :only }))
464
- count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
465
- batch_count = (count.to_f/5000.0).ceil
466
-
467
- ids = []
468
- k = m.remote_key_field
469
- (0...batch_count).each do |i|
470
- self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
471
- ids << data[k]
472
- # ids << case class_type
473
- # when 'RES' then data[k]
474
- # when 'COM' then data[k]
475
- # when 'LND' then data[k]
476
- # when 'MUL' then data[k]
477
- # when 'OFF' then data[k]
478
- # when 'AGT' then data[k]
479
- # when 'OPH' then data[k].to_i
480
- # when 'GFX' then data[k]
481
- # end
482
- end
483
- end
484
-
485
- if ids.count > 0
486
- # Delete any records in the local database that shouldn't be there
487
- t = m.local_table
488
- k = m.local_key_field
489
- query = ["delete from #{t} where #{k} not in (?)", ids]
490
- ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
491
-
492
- # Find any ids in the remote database that should be in the local database
493
- query = "select distinct #{k} from #{t}"
494
- rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
495
- local_ids = rows.collect{ |row| row[k] }
496
- ids_to_add = ids - local_ids
497
- ids_to_add.each do |id|
498
- self.log("Importing #{id}...")
499
- self.delay(:priority => 10, :queue => 'rets').import_properties(id, false)
500
- # case class_type
501
- # when 'RES' then self.delay(:queue => 'rets').import_residential_property(id, false)
502
- # when 'COM' then self.delay(:queue => 'rets').import_commercial_property(id, false)
503
- # when 'LND' then self.delay(:queue => 'rets').import_land_property(id, false)
504
- # when 'MUL' then self.delay(:queue => 'rets').import_multi_family_property(id, false)
505
- # when 'OFF' then self.delay(:queue => 'rets').import_office(id, false)
506
- # when 'AGT' then self.delay(:queue => 'rets').import_agent(id, false)
507
- # when 'OPH' then self.delay(:queue => 'rets').import_open_house(id, false)
508
- # when 'GFX' then self.delay(:queue => 'rets').import_media(id)
509
- # end
510
- end
511
- end
512
-
513
- end
514
-
515
- #=============================================================================
516
- # Logging
517
- #=============================================================================
518
-
519
- def self.log(msg)
520
- puts "[rets_importer] #{msg}"
521
- #Rails.logger.info("[rets_importer] #{msg}")
522
- end
523
-
524
- def self.log2(msg)
525
- puts "======================================================================"
526
- puts "[rets_importer] #{msg}"
527
- puts "======================================================================"
528
- #Rails.logger.info("[rets_importer] #{msg}")
529
- end
530
-
531
- #=============================================================================
532
- # Locking update task
533
- #=============================================================================
534
-
535
- def self.update_rets
536
- self.log2("Updating rets...")
537
- if self.task_is_locked
538
- self.log2("Task is locked, aborting.")
539
- return
540
- end
541
- self.log2("Locking task...")
542
- task_started = self.lock_task
543
-
544
- begin
545
- overlap = 30.seconds
546
- if (DateTime.now - self.last_purged).to_i >= 1
547
- self.purge
548
- self.save_last_purged(task_started)
549
- # Keep this in here to make sure all updates are caught
550
- #overlap = 1.month
551
- end
552
-
553
- self.log2("Updating after #{self.last_updated.strftime("%FT%T%:z")}...")
554
- self.update_after(self.last_updated - overlap)
555
-
556
- self.log2("Saving the timestamp for when we updated...")
557
- self.save_last_updated(task_started)
558
-
559
- self.log2("Unlocking the task...")
560
- self.unlock_task
561
- rescue Exception => err
562
- puts err
563
- raise
564
- ensure
565
- self.log2("Unlocking task if last updated...")
566
- self.unlock_task_if_last_updated(task_started)
567
- end
568
-
569
- # Start the same update process in five minutes
570
- self.log2("Adding the update rets task for 5 minutes from now...")
571
- q = "handler like '%update_rets%'"
572
- count = Delayed::Job.where(q).count
573
- if count == 0 || (count == 1 && Delayed::Job.where(q).first.locked_at)
574
- self.delay(:run_at => 5.minutes.from_now, :priority => 10, :queue => 'rets').update_rets
575
- end
576
- end
577
-
578
- def self.last_updated
579
- if !Caboose::Setting.exists?(:name => 'rets_last_updated')
580
- Caboose::Setting.create(:name => 'rets_last_updated', :value => '2013-08-06T00:00:01')
581
- end
582
- s = Caboose::Setting.where(:name => 'rets_last_updated').first
583
- return DateTime.parse(s.value)
584
- end
585
-
586
- def self.last_purged
587
- if !Caboose::Setting.exists?(:name => 'rets_last_purged')
588
- Caboose::Setting.create(:name => 'rets_last_purged', :value => '2013-08-06T00:00:01')
589
- end
590
- s = Caboose::Setting.where(:name => 'rets_last_purged').first
591
- return DateTime.parse(s.value)
592
- end
593
-
594
- def self.save_last_updated(d)
595
- s = Caboose::Setting.where(:name => 'rets_last_updated').first
596
- s.value = d.in_time_zone(CabooseRets::timezone).strftime("%FT%T%:z")
597
- s.save
598
- end
599
-
600
- def self.save_last_purged(d)
601
- s = Caboose::Setting.where(:name => 'rets_last_purged').first
602
- s.value = d.in_time_zone(CabooseRets::timezone).strftime("%FT%T%:z")
603
- s.save
604
- end
605
-
606
- def self.task_is_locked
607
- return Caboose::Setting.exists?(:name => 'rets_update_running')
608
- end
609
-
610
- def self.lock_task
611
- d = DateTime.now.utc.in_time_zone(CabooseRets::timezone)
612
- Caboose::Setting.create(:name => 'rets_update_running', :value => d.strftime("%FT%T%:z"))
613
- return d
614
- end
615
-
616
- def self.unlock_task
617
- Caboose::Setting.where(:name => 'rets_update_running').first.destroy
618
- end
619
-
620
- def self.unlock_task_if_last_updated(d)
621
- setting = Caboose::Setting.where(:name => 'rets_update_running').first
622
- self.unlock_task if setting && d.in_time_zone.strftime("%FT%T%:z") == setting.value
623
- end
624
-
625
- end