Class: CabooseRets::RetsImporter

Inherits:
Object
  • Object
show all
Defined in:
app/models/caboose_rets/rets_importer.rb,
app/models/caboose_rets/rets_importer_old.rb

Overview

Constant Summary collapse

@@rets_client =

< ActiveRecord::Base

nil
@@config =
nil

Class Method Summary collapse

Class Method Details

.clientObject



39
40
41
42
43
44
45
46
47
48
49
50
# File 'app/models/caboose_rets/rets_importer.rb', line 39

def self.client
  self.get_config if @@config.nil? || @@config['url'].nil?

  if @@rets_client.nil?
    @@rets_client = RETS::Client.(
      :url      => @@config['url'],
      :username => @@config['username'],
      :password => @@config['password']
    )
  end
  return @@rets_client
end

.configObject



21
22
23
# File 'app/models/caboose_rets/rets_importer.rb', line 21

def self.config
  return @@config
end

.coords_from_address(address) ⇒ Object



335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'app/models/caboose_rets/rets_importer.rb', line 335

def self.coords_from_address(address)
  #return false
  begin
    uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
    uri.gsub!(" ", "+")
    resp = HTTParty.get(uri)
    json = JSON.parse(resp.body)
    return json['results'][0]['geometry']['location']
  rescue
    self.log "Error: #{uri}"
    sleep(2)
    return false
  end
end

.download_agent_image(agent) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'app/models/caboose_rets/rets_importer.rb', line 280

def self.download_agent_image(agent)
  self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
  begin
    self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => property.list_agent_mls_id) do |headers, content|
      agent.verify_meta_exists
      agent.meta.image_location = headers['location']
      agent.meta.save
    end
  rescue RETS::APIError => err
    self.log "No image for #{agent.first_name} #{agent.last_name}."
    self.log err
  end
end

.download_office_image(office) ⇒ Object



294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'app/models/caboose_rets/rets_importer.rb', line 294

def self.download_office_image(office)
  #self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
  #begin
  #  self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => agent.la_code) do |headers, content|
  #    agent.verify_meta_exists
  #    agent.meta.image_location = headers['location']
  #    agent.meta.save
  #  end
  #rescue RETS::APIError => err
  #  self.log "No image for #{agent.first_name} #{agent.last_name}."
  #  self.log err
  #end
end

.download_property_images(p, save_images = true) ⇒ Object

Images



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'app/models/caboose_rets/rets_importer.rb', line 238

def self.download_property_images(p)
  self.log "Saving images for #{p.matrix_unique_id}..."
  begin
    # url = "http://rets.wamls.mlsmatrix.com/rets/GetObject.ashx?Type=Photo&Resource=Property&ID=1026514:1"
    self.client.get_object(:resource => 'Property', :type => 'Photo', :location=> false, :id => "#{p.matrix_unique_id}:*") do |headers, content|
      m = CabooseRets::Media.where(:media_mui => headers['content-id'], :media_order => headers['object-id']).first
      m = CabooseRets::Media.new if m.nil?

      tmp_path = "#{Rails.root}/tmp/rets_media_#{headers['content-id']}:#{headers['object-id']}.jpeg"

      # Temporarily cache content
      File.open(tmp_path, "wb") do |f|
        f.write(content)
      end

      # Parse downloaded content
      m.media_mui     = headers['content-id']
      m.media_order   = headers['object-id']
      m.media_remarks = headers['content-description']
      m.media_type    = 'Photo'

      cm               = Caboose::Media.new
      cm.image         = File.open(tmp_path)
      cm.name          = "rets_media_#{headers['content-id']}_#{headers['object-id']}"
      cm.original_name = "rets_media_#{headers['content-id']}_#{headers['object-id']}.jpeg"
      cm.processed     = true
      cm.save

      m.media_id = cm.id
      m.save

      # Remove temporary file
      `rm #{tmp_path}`

      self.log("Image #{headers['content-id']}:#{headers['object-id']} saved")
    end
  rescue RETS::APIError => err
    self.log "No image for #{p.matrix_unique_id}."
    self.log err
  end
end

.get_configObject



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'app/models/caboose_rets/rets_importer.rb', line 25

def self.get_config
  @@config = {
    'url'                 => nil, # URL to the RETS login
    'username'            => nil,
    'password'            => nil,
    'temp_path'           => nil,
    'log_file'            => nil,
    'media_base_url'      => nil
  }
  config = YAML::load(File.open("#{Rails.root}/config/rets_importer.yml"))    
  config = config[Rails.env]
  config.each { |key,val| @@config[key] = val }
end

.get_instance_with_id(class_type, data) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'app/models/caboose_rets/rets_importer.rb', line 95

def self.get_instance_with_id(class_type, data)
  obj = nil
  m = case class_type
    when 'Listing'   then CabooseRets::Property
    when 'OpenHouse' then CabooseRets::OpenHouse
    when 'Agent'     then CabooseRets::Agent
    when 'Office'    then CabooseRets::Office
    when 'GFX'       then CabooseRets::Media
  end  
  obj  = case class_type
    when 'Listing'   then m.where(:matrix_unique_id => data['Matrix_Unique_ID']).exists? ? m.where(:matrix_unique_id => data['Matrix_Unique_ID']).first : m.new(:matrix_unique_id => data['Matrix_Unique_ID'])
    when 'OpenHouse' then m.where(:matrix_unique_id => data['matrix_unique_id']).exists? ? m.where(:matrix_unique_id => data['matrix_unique_id']).first : m.new(:matrix_unique_id => data['matrix_unique_id'])
    when 'Agent'     then m.where(:matrix_unique_id => data['Matrix_Unique_ID']).exists? ? m.where(:matrix_unique_id => data['Matrix_Unique_ID']).first : m.new(:matrix_unique_id => data['Matrix_Unique_ID'])
    when 'Office'    then m.where(:matrix_unique_id => data['Matrix_Unique_ID']).exists? ? m.where(:matrix_unique_id => data['Matrix_Unique_ID']).first : m.new(:matrix_unique_id => data['Matrix_Unique_ID'])
    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']      )
  end
  return obj
end

.get_media_urlsObject



433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'app/models/caboose_rets/rets_importer.rb', line 433

def self.get_media_urls
  m = self.meta(class_type)

  # Get the total number of records
  params = {
    :search_type => m.search_type,
    :class => class_type,
    :query => "(#{m.matrix_modified_dt}=#{date_modified}T00:00:01+)",
    :standard_names_only => true,
    :timeout => -1
  }
  self.client.search(params.merge({ :count => 1 }))
  count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
  batch_count = (count.to_f/5000.0).ceil

  ids = []
  k = m.remote_key_field
  (0...batch_count).each do |i|
    self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
      ids << data[k]
    end
  end

  if ids.count > 0
    # Delete any records in the local database that shouldn't be there
    t = m.local_table
    k = m.local_key_field
    query = ["delete from #{t} where #{k} not in (?)", ids]
    ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))

    # Find any ids in the remote database that should be in the local database
    query = "select distinct #{k} from #{t}"      
    rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
    local_ids = rows.collect{ |row| row[k] }
    ids_to_add = ids - local_ids
    ids_to_add.each do |id|
      self.log("Importing #{id}...")
      case class_type
        when "Listing"   then self.delay(:priority => 10, :queue => 'rets').import_properties(id, false)
        when "Office"    then self.delay(:priority => 10, :queue => 'rets').import_office(id, false)
        when "Agent"     then self.delay(:priority => 10, :queue => 'rets').import_agent(id, false)
        when "OpenHouse" then self.delay(:priority => 10, :queue => 'rets').import_open_house(id, false)
      end
    end
  end

end

.import(class_type, query) ⇒ Object

Import method



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/models/caboose_rets/rets_importer.rb', line 66

def self.import(class_type, query)
  m = self.meta(class_type)
  self.log("Importing #{m.search_type}:#{class_type} with query #{query}...")
  self.get_config if @@config.nil? || @@config['url'].nil?
  params = {
    :search_type => m.search_type,
    :class => class_type,
    :query => query,
    :timeout => -1
  }
  obj = nil

  begin
    self.client.search(params) do |data|
      obj = self.get_instance_with_id(class_type, data)
      if obj.nil?
        self.log("Error: object is nil")
        self.log(data.inspect)
        next
      end
      obj.parse(data)
      obj.save
    end
  rescue RETS::HTTPError => err
    self.log "Import error for #{class_type}: #{query}"
    self.log err.message
  end
end

.import_agent(mui, save_images = true) ⇒ Object



182
183
184
185
186
# File 'app/models/caboose_rets/rets_importer.rb', line 182

def self.import_agent(mui, save_images = true)
  self.import('Agent', "(Matrix_Unique_ID=#{mui})")
  a = CabooseRets::Agent.where(:matrix_unique_id => mui.to_s).first
  # self.download_agent_image(a) #if save_images == true
end

.import_media(id, save_images = true) ⇒ Object

def self.import_residential_property(mls, save_images = true)

self.import('RES', "(MLS=*#{mls}*)")
p = CabooseRets::ResidentialProperty.where(:id => mls.to_i).first
self.download_property_images(p, save_images)
self.update_coords(p)

end

def self.import_commercial_property(mls, save_images = true)

self.import('COM', "(MLS=*#{mls}*)")
p = CabooseRets::CommercialProperty.where(:id => mls.to_i).first
self.download_property_images(p, save_images)
self.update_coords(p)

end

def self.import_land_property(mls, save_images = true)

self.import('LND', "(MLS=*#{mls}*)")
p = CabooseRets::LandProperty.where(:id => mls.to_i).first
self.download_property_images(p, save_images)
self.update_coords(p)

end

def self.import_multi_family_property(mls, save_images = true)

self.import('MUL', "(MLS=*#{mls}*)")
p = CabooseRets::MultiFamilyProperty.where(:id => mls.to_i).first
self.download_property_images(p, save_images)
self.update_coords(p)

end

def self.import_office(lo_code, save_images = true)

self.import('OFF', "(LO_LO_CODE=*#{lo_code}*)")
office = CabooseRets::Office.where(:lo_code => lo_code.to_s).first
self.download_office_image(office) if save_images == true

end

def self.import_agent(la_code, save_images = true)

self.import('AGT', "(LA_LA_CODE=*#{la_code}*)")
a = CabooseRets::Agent.where(:la_code => la_code.to_s).first
self.download_agent_image(a) #if save_images == true

end

def self.import_open_house(id, save_images = true)

self.import('OPH', "((ID=#{id}+),(ID=#{id}-))")

end



240
241
242
# File 'app/models/caboose_rets/rets_importer_old.rb', line 240

def self.import_media(id, save_images = true)
  self.import('GFX', "((MEDIA_ID=#{id}+),(MEDIA_ID=#{id}-))")
end

.import_office(mui, save_images = true) ⇒ Object



176
177
178
179
180
# File 'app/models/caboose_rets/rets_importer.rb', line 176

def self.import_office(mui, save_images = true)
  self.import('Office', "(matrix_unique_id=#{mui})")
  office = CabooseRets::Office.where(:matrix_unique_id => mui.to_s).first
  # self.download_office_image(office) if save_images == true
end

.import_open_house(mui, save_images = true) ⇒ Object



188
189
190
# File 'app/models/caboose_rets/rets_importer.rb', line 188

def self.import_open_house(mui, save_images = true)
  self.import('OpenHouse', "(Matrix_Unique_ID=#{mui})")
end

.import_properties(mls, save_images = true) ⇒ Object

def self.import_property(mui, save_images = true)

self.import('Listing', "(Matrix_Unique_ID=#{mui})")
p = CabooseRets::Property.where(:matrix_unique_id => mui.to_s).first
if p != nil
  self.download_property_images(p)
  self.update_coords(p)
else
  self.log("No Property associated with #{mui}")
end

end



164
165
166
167
168
169
170
171
172
173
174
# File 'app/models/caboose_rets/rets_importer.rb', line 164

def self.import_properties(mui, save_images = true)
  self.import('Listing', "(Matrix_Unique_ID=#{mui})")
  p = CabooseRets::Property.where(:matrix_unique_id => mui.to_s).first
  # p = CabooseRets::Property.create(:matrix_unique_id => mui.to_s) if p.nil?
  if p != nil
    self.download_property_images(p)
    self.update_coords(p)
  else
    self.log("No Property associated with #{mui}")
  end
end

.import_property(mls, save_images = true) ⇒ Object

Single model import methods (called from a worker dyno)



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'app/models/caboose_rets/rets_importer_old.rb', line 169

def self.import_property(mls, save_images = true)
  self.import('RES', "(MLS=*#{mls}*)")
  p = CabooseRets::Property.where(:id => mls.to_i).first
  # p = CabooseRets::ResidentialProperty.where(:id => mls.to_i).first
  # if p.nil?
  #   self.import('COM', "(MLS=*#{mls}*)")
  #   p = CabooseRets::CommercialProperty.where(:id => mls.to_i).first
  #   if p.nil?
  #     self.import('LND', "(MLS=*#{mls}*)")
  #     p = CabooseRets::LandProperty.where(:id => mls.to_i).first
  #     if p.nil?
  #       self.import('MUL', "(MLS=*#{mls}*)")
  #       p = CabooseRets::MultiFamilyProperty.where(:id => mls.to_i).first
  #       return if p.nil?
  #     end
  #   end
  # end
  self.download_property_images(p, save_images)
end

.last_purgedObject



552
553
554
555
556
557
558
# File 'app/models/caboose_rets/rets_importer.rb', line 552

def self.last_purged
  if !Caboose::Setting.exists?(:name => 'rets_last_purged')
    Caboose::Setting.create(:name => 'rets_last_purged', :value => '2013-08-06T00:00:01')
  end
  s = Caboose::Setting.where(:name => 'rets_last_purged').first
  return DateTime.parse(s.value)
end

.last_updatedObject



544
545
546
547
548
549
550
# File 'app/models/caboose_rets/rets_importer.rb', line 544

def self.last_updated
  if !Caboose::Setting.exists?(:name => 'rets_last_updated')
    Caboose::Setting.create(:name => 'rets_last_updated', :value => '2013-08-06T00:00:01')
  end
  s = Caboose::Setting.where(:name => 'rets_last_updated').first
  return DateTime.parse(s.value)
end

.lock_taskObject



576
577
578
579
580
# File 'app/models/caboose_rets/rets_importer.rb', line 576

def self.lock_task
  d = DateTime.now.utc.in_time_zone(CabooseRets::timezone)
  Caboose::Setting.create(:name => 'rets_update_running', :value => d.strftime("%FT%T%:z"))
  return d
end

.log(msg) ⇒ Object

Logging



485
486
487
488
# File 'app/models/caboose_rets/rets_importer.rb', line 485

def self.log(msg)
  puts "[rets_importer] #{msg}"
  #Rails.logger.info("[rets_importer] #{msg}")
end

.log2(msg) ⇒ Object



490
491
492
493
494
495
# File 'app/models/caboose_rets/rets_importer.rb', line 490

def self.log2(msg)
  puts "======================================================================"
  puts "[rets_importer] #{msg}"
  puts "======================================================================"
  #Rails.logger.info("[rets_importer] #{msg}")
end

.meta(class_type) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'app/models/caboose_rets/rets_importer.rb', line 52

def self.meta(class_type)
  case class_type
    when 'Office'    then Caboose::StdClass.new({ :search_type => 'Office'    , :remote_key_field => 'Matrix_Unique_ID' , :local_key_field => 'matrix_unique_id'    , :local_table => 'rets_offices'      , :date_modified_field => 'MatrixModifiedDT'})
    when 'Agent'     then Caboose::StdClass.new({ :search_type => 'Agent'     , :remote_key_field => 'Matrix_Unique_ID' , :local_key_field => 'matrix_unique_id'    , :local_table => 'rets_agents'       , :date_modified_field => 'MatrixModifiedDT'})
    when 'OpenHouse' then Caboose::StdClass.new({ :search_type => 'OpenHouse' , :remote_key_field => 'matrix_unique_id' , :local_key_field => 'matrix_unique_id'    , :local_table => 'rets_open_houses'  , :date_modified_field => 'MatrixModifiedDT'})
    when 'Listing'   then Caboose::StdClass.new({ :search_type => 'Property'  , :remote_key_field => 'Matrix_Unique_ID' , :local_key_field => 'matrix_unique_id'    , :local_table => 'rets_properties'   , :date_modified_field => 'MatrixModifiedDT'})
    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'   })
    end
end

.purgeObject

Purging



354
355
356
357
358
359
360
# File 'app/models/caboose_rets/rets_importer.rb', line 354

def self.purge
  self.log('purging')
  self.purge_properties
  self.purge_offices
  #self.purge_agents
  self.purge_open_houses
end

.purge_agentsObject



364
# File 'app/models/caboose_rets/rets_importer.rb', line 364

def self.purge_agents()       self.delay(:priority => 10, :queue => 'rets').purge_helper('Agent', '2012-01-01') end

.purge_commercialObject



374
# File 'app/models/caboose_rets/rets_importer_old.rb', line 374

def self.purge_commercial()   self.delay(:priority => 10, :queue => 'rets').purge_helper('COM', '2012-01-01') end

.purge_helper(class_type, date_modified) ⇒ Object



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'app/models/caboose_rets/rets_importer.rb', line 368

def self.purge_helper(class_type, date_modified)    
  m = self.meta(class_type)    
  self.log(m.search_type)

  self.log("Purging #{class_type}...")

  # Get the total number of records
  self.log("- Getting total number of records for #{class_type}...")
  params = {
    :search_type => m.search_type,
    :class => class_type,
    :query => "(#{m.date_modified_field}=#{date_modified}T00:00:01+)",
    :standard_names_only => true,
    :timeout => -1
  }
  count = 0
  self.client.search(params.merge({ :count => 1})) do |data| end        
  count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]    
  batch_count = (count.to_f/5000.0).ceil

  ids = []
  k = m.remote_key_field
  (0...batch_count).each do |i|
    self.log("- Getting ids for #{class_type} (batch #{i+1} of #{batch_count})...")
    self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
      ids << (class_type == 'OpenHouse' ? data[k].to_i : data[k])
    end
  end

  # Only do stuff if we got a real response from the server
  if ids.count > 0

    # Delete any records in the local database that shouldn't be there
    self.log("- Finding #{class_type} records in the local database that are not in the remote database...")
    t = m.local_table
    k = m.local_key_field
    query = "select distinct #{k} from #{t}"
    rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
    local_ids = rows.collect{ |row| row[k] }
    ids_to_remove = local_ids - ids
    self.log("- Found #{ids_to_remove.count} #{class_type} records in the local database that are not in the remote database.")
    self.log("- Deleting #{class_type} records in the local database that shouldn't be there...")
    query = ["delete from #{t} where #{k} in (?)", ids_to_remove]
    ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))

    # Find any ids in the remote database that should be in the local database
    self.log("- Finding #{class_type} records in the remote database that should be in the local database...")
    query = "select distinct #{k} from #{t}"
    rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
    local_ids = rows.collect{ |row| row[k] }
    ids_to_add = ids - local_ids
    ids_to_add = ids_to_add.sort.reverse
    self.log("- Found #{ids_to_add.count} #{class_type} records in the remote database that we need to add to the local database.")
    ids_to_add.each do |id|
      self.log("- Importing #{id}...")
      case class_type
        when "Listing"   then self.delay(:priority => 10, :queue => 'rets').import_properties(id, false)
        when "Office"    then self.delay(:priority => 10, :queue => 'rets').import_office(id, false)
        when "Agent"     then self.delay(:priority => 10, :queue => 'rets').import_agent(id, false)
        when "OpenHouse" then self.delay(:priority => 10, :queue => 'rets').import_open_house(id, false)
      end
    end
  end
end

.purge_landObject



375
# File 'app/models/caboose_rets/rets_importer_old.rb', line 375

def self.purge_land()         self.delay(:priority => 10, :queue => 'rets').purge_helper('LND', '2012-01-01') end

.purge_mediaObject



380
# File 'app/models/caboose_rets/rets_importer_old.rb', line 380

def self.purge_media()        self.delay(:priority => 10, :queue => 'rets').purge_helper('GFX', '2012-01-01') end

.purge_multi_familyObject



376
# File 'app/models/caboose_rets/rets_importer_old.rb', line 376

def self.purge_multi_family() self.delay(:priority => 10, :queue => 'rets').purge_helper('MUL', '2012-01-01') end

.purge_officesObject



363
# File 'app/models/caboose_rets/rets_importer.rb', line 363

def self.purge_offices()      self.delay(:priority => 10, :queue => 'rets').purge_helper('Office', '2012-01-01') end

.purge_open_housesObject



365
# File 'app/models/caboose_rets/rets_importer.rb', line 365

def self.purge_open_houses()  self.delay(:priority => 10, :queue => 'rets').purge_helper('OpenHouse', '2012-01-01') end

.purge_propertiesObject



362
# File 'app/models/caboose_rets/rets_importer.rb', line 362

def self.purge_properties()   self.delay(:priority => 10, :queue => 'rets').purge_helper('Listing', '2012-01-01') end

.purge_residentialObject



373
# File 'app/models/caboose_rets/rets_importer_old.rb', line 373

def self.purge_residential()  self.delay(:priority => 10, :queue => 'rets').purge_helper('RES', '2012-01-01') end

.save_last_purged(d) ⇒ Object



566
567
568
569
570
# File 'app/models/caboose_rets/rets_importer.rb', line 566

def self.save_last_purged(d)
  s = Caboose::Setting.where(:name => 'rets_last_purged').first
  s.value = d.in_time_zone(CabooseRets::timezone).strftime("%FT%T%:z")
  s.save
end

.save_last_updated(d) ⇒ Object



560
561
562
563
564
# File 'app/models/caboose_rets/rets_importer.rb', line 560

def self.save_last_updated(d)
  s = Caboose::Setting.where(:name => 'rets_last_updated').first
  s.value = d.in_time_zone(CabooseRets::timezone).strftime("%FT%T%:z")
  s.save
end

.task_is_lockedObject



572
573
574
# File 'app/models/caboose_rets/rets_importer.rb', line 572

def self.task_is_locked
  return Caboose::Setting.exists?(:name => 'rets_update_running')
end

.unlock_taskObject



582
583
584
# File 'app/models/caboose_rets/rets_importer.rb', line 582

def self.unlock_task
  Caboose::Setting.where(:name => 'rets_update_running').first.destroy
end

.unlock_task_if_last_updated(d) ⇒ Object



586
587
588
589
# File 'app/models/caboose_rets/rets_importer.rb', line 586

def self.unlock_task_if_last_updated(d)
  setting = Caboose::Setting.where(:name => 'rets_update_running').first
  self.unlock_task if setting && d.in_time_zone.strftime("%FT%T%:z") == setting.value
end

.update_after(date_modified, save_images = true) ⇒ Object

Main updater



118
119
120
121
122
123
# File 'app/models/caboose_rets/rets_importer.rb', line 118

def self.update_after(date_modified, save_images = true)
  self.delay(:priority => 10, :queue => 'rets').update_helper('Listing'  , date_modified, save_images)
  self.delay(:priority => 10, :queue => 'rets').update_helper('Office'   , date_modified, save_images)
  self.delay(:priority => 10, :queue => 'rets').update_helper('Agent'    , date_modified, save_images)
  self.delay(:priority => 10, :queue => 'rets').update_helper('OpenHouse', date_modified, save_images)
end

.update_coords(p = nil) ⇒ Object

GPS



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'app/models/caboose_rets/rets_importer.rb', line 312

def self.update_coords(p = nil)
  if p.nil?
    model = CabooseRets::Property      
    i = 0      
      self.log "Updating coords properties..."
      model.where(:latitude => nil).reorder(:matrix_unique_id).each do |p1|
        self.delay(:priority => 10, :queue => 'rets').update_coords(p1)
      end
    return
  end

  self.log "Getting coords for Matrix_Unique_ID #{p.matrix_unique_id}..."
  coords = self.coords_from_address(CGI::escape "#{p.street_number} #{p.street_name}, #{p.city}, #{p.state_or_province} #{p.postal_code}")
  if coords.nil? || coords == false
    self.log "Can't set coords for Matrix_Unique_ID #{p.matrix_unique_id}..."
    return
  end

  p.latitude = coords['lat']
  p.longitude = coords['lng']
  p.save
end

.update_helper(class_type, date_modified, save_images = true) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'app/models/caboose_rets/rets_importer.rb', line 125

def self.update_helper(class_type, date_modified, save_images = true)    
  m = self.meta(class_type)
  k = m.remote_key_field
  d = date_modified.in_time_zone(CabooseRets::timezone).strftime("%FT%T")
  params = {
    :search_type => m.search_type,
    :class => class_type,
    :select => [m.remote_key_field],
    :querytype => 'DMQL2',
    :query => "(#{m.date_modified_field}=#{d}+)",
    :standard_names_only => true,
    :timeout => -1
  }    
  self.log(params)
  self.client.search(params) do |data|    
    case class_type
      when 'Listing'   then self.delay(:priority => 10, :queue => 'rets').import_properties(data[k], save_images)
      when 'Office'    then self.delay(:priority => 10, :queue => 'rets').import_office(    data[k], save_images)
      when 'Agent'     then self.delay(:priority => 10, :queue => 'rets').import_agent(     data[k], save_images)
      when 'OpenHouse' then self.delay(:priority => 10, :queue => 'rets').import_open_house(data[k], save_images)
    end
  end
end

.update_retsObject

Locking update task



501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
# File 'app/models/caboose_rets/rets_importer.rb', line 501

def self.update_rets
  self.log2("Updating rets...")
  if self.task_is_locked
    self.log2("Task is locked, aborting.")
    return
  end
  self.log2("Locking task...")
  task_started = self.lock_task

  begin
    overlap = 30.seconds
    if (DateTime.now - self.last_purged).to_i >= 1
      self.purge
      self.save_last_purged(task_started)
      # Keep this in here to make sure all updates are caught
      #overlap = 1.month
    end

    self.log2("Updating after #{self.last_updated.strftime("%FT%T%:z")}...")
    self.update_after(self.last_updated - overlap)

    self.log2("Saving the timestamp for when we updated...")
  self.save_last_updated(task_started)

  self.log2("Unlocking the task...")
  self.unlock_task
rescue Exception => err
  puts err
  raise
ensure
  self.log2("Unlocking task if last updated...")
  self.unlock_task_if_last_updated(task_started)
  end

# Start the same update process in five minutes
self.log2("Adding the update rets task for 20 minutes from now...")
q = "handler like '%update_rets%'"
count = Delayed::Job.where(q).count
if count == 0 || (count == 1 && Delayed::Job.where(q).first.locked_at)
  self.delay(:run_at => 20.minutes.from_now, :priority => 10, :queue => 'rets').update_rets
end
end