caboose-rets 0.0.69 → 0.0.70
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/app/controllers/caboose_rets/media_controller.rb +3 -3
- data/app/models/caboose_rets/agent.rb +8 -0
- data/app/models/caboose_rets/media.rb +10 -2
- data/app/models/caboose_rets/rets_importer.rb +114 -86
- data/app/models/caboose_rets/rets_importer_bak.rb +621 -0
- data/app/models/caboose_rets/schema.rb +8 -2
- data/app/views/caboose_rets/residential/index.html.erb +1 -1
- data/lib/caboose-rets.rb +13 -1
- data/lib/caboose_rets/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MWExNTE4ZTRhZDM1MDUxY2YwNzllZTA4ZjgxMTJhZjNmNjQ2ZDdhNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZmM4YmY1MWM3MWUxOGExMjY2M2NhYmVlYzA1MWRhOWVmMWE1ZTY2OA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjcwNzQyZjkwMjg5NTYwN2M1ODkxMDhkNzQxNWQ5ZGVlYTQ5ZDZkYjkxY2Qy
|
10
|
+
YzAxZDAxMTFmNjI4Y2U0ODYzNmQyM2YwMzIyOGUzNjkzNDUwMWRlNjFkMTdl
|
11
|
+
OGVhN2QxMjZmZDRhNWVlNzI2MDJhNjRjYzRiZDEyNTg4ZDU2Mjk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OGYzODJjYTBmNzQwMTI4MWUyZDBkNDMwMGU3ZmY1YmU5MjdjZGE5ZDMyMzZi
|
14
|
+
YzI0NDgwNmVjZTQ5NDE5ODY4NzZmYTEzODIwM2I1YmQ4N2JlMWMwMzgwMmM4
|
15
|
+
ZTY0OTg4OTcxNWI5MWY2MjJhYTllZTE0ZmUzYTI1Y2U3Y2NhMmM=
|
@@ -102,9 +102,9 @@ module CabooseRets
|
|
102
102
|
:content_type => m.image_content_type,
|
103
103
|
:file_size => m.image_file_size,
|
104
104
|
:update_at => m.image_updated_at,
|
105
|
-
:tiny_url => m.
|
106
|
-
:thumb_url => m.
|
107
|
-
:large_url => m.
|
105
|
+
:tiny_url => m.image_url(:tiny),
|
106
|
+
:thumb_url => m.image_url(:thumb),
|
107
|
+
:large_url => m.image_url(:large)
|
108
108
|
},
|
109
109
|
:file => {
|
110
110
|
:file_name => m.file_file_name,
|
@@ -76,5 +76,13 @@ class CabooseRets::Agent < ActiveRecord::Base
|
|
76
76
|
self.photo_date_modified = data['PHOTO_DATE_MODIFIED']
|
77
77
|
#self.photo_url = ""
|
78
78
|
end
|
79
|
+
|
80
|
+
def image_url(style)
|
81
|
+
if CabooseRets::use_hosted_images == true
|
82
|
+
return "#{CabooseRets::agents_base_url}/#{self.image_file_name}"
|
83
|
+
end
|
84
|
+
return "" if self.image.nil?
|
85
|
+
return self.image.url(style)
|
86
|
+
end
|
79
87
|
|
80
88
|
end
|
@@ -18,7 +18,7 @@ class CabooseRets::Media < ActiveRecord::Base
|
|
18
18
|
self.date_modified = data['DATE_MODIFIED']
|
19
19
|
self.file_name = data['FILE_NAME']
|
20
20
|
self.media_id = data['MEDIA_ID']
|
21
|
-
self.media_order = data['MEDIA_ORDER']
|
21
|
+
self.media_order = data['MEDIA_ORDER'].to_i
|
22
22
|
self.media_remarks = data['MEDIA_REMARKS']
|
23
23
|
self.media_type = data['MEDIA_TYPE']
|
24
24
|
self.mls_acct = data['MLS_ACCT']
|
@@ -122,5 +122,13 @@ class CabooseRets::Media < ActiveRecord::Base
|
|
122
122
|
|
123
123
|
return true
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
|
+
def image_url(style)
|
127
|
+
if CabooseRets::use_hosted_images == true
|
128
|
+
return "#{CabooseRets::media_base_url}/#{self.file_name}"
|
129
|
+
end
|
130
|
+
return "" if self.image.nil?
|
131
|
+
return self.image.url(style)
|
132
|
+
end
|
133
|
+
|
126
134
|
end
|
@@ -78,16 +78,22 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
78
78
|
:timeout => -1
|
79
79
|
}
|
80
80
|
obj = nil
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
begin
|
82
|
+
self.client.search(params) do |data|
|
83
|
+
obj = self.get_instance_with_id(class_type, data)
|
84
|
+
if obj.nil?
|
85
|
+
self.log("Error: object is nil")
|
86
|
+
self.log(data.inspect)
|
87
|
+
next
|
88
|
+
end
|
89
|
+
obj.parse(data)
|
90
|
+
obj.save
|
87
91
|
end
|
88
|
-
|
89
|
-
|
92
|
+
rescue RETS::HTTPError => err
|
93
|
+
self.log "Import error for #{class_type}: #{query}"
|
94
|
+
self.log err.message
|
90
95
|
end
|
96
|
+
|
91
97
|
end
|
92
98
|
|
93
99
|
def self.get_instance_with_id(class_type, data)
|
@@ -204,7 +210,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
204
210
|
self.update_coords(p)
|
205
211
|
end
|
206
212
|
|
207
|
-
def self.import_office(lo_code, save_images = true)
|
213
|
+
def self.import_office(lo_code, save_images = true)
|
208
214
|
self.import('OFF', "(LO_LO_CODE=*#{lo_code}*)")
|
209
215
|
office = CabooseRets::Office.where(:lo_code => lo_code.to_s).first
|
210
216
|
self.download_office_image(office) if save_images == true
|
@@ -221,97 +227,43 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
221
227
|
end
|
222
228
|
|
223
229
|
def self.import_media(id, save_images = true)
|
224
|
-
self.import('GFX', "((MEDIA_ID=#{id}+),(MEDIA_ID=#{id}-))")
|
225
|
-
#self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
|
226
|
-
#
|
227
|
-
# # Find the associated media record for the image
|
228
|
-
# filename = File.basename(headers['location'])
|
229
|
-
# m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
|
230
|
-
#
|
231
|
-
# if m.nil?
|
232
|
-
# self.log("Can't find media record for #{p.mls_acct} #{filename}.")
|
233
|
-
# else
|
234
|
-
# m.image = URI.parse(headers['location'])
|
235
|
-
# media << m
|
236
|
-
# #m.save
|
237
|
-
# end
|
238
|
-
#end
|
230
|
+
self.import('GFX', "((MEDIA_ID=#{id}+),(MEDIA_ID=#{id}-))")
|
239
231
|
end
|
240
232
|
|
241
233
|
#=============================================================================
|
242
234
|
# Images
|
243
235
|
#=============================================================================
|
244
|
-
|
236
|
+
|
245
237
|
def self.download_property_images(p, save_images = true)
|
246
|
-
self.refresh_property_media(p)
|
247
238
|
return if save_images == false
|
248
|
-
|
249
|
-
self.log("
|
250
|
-
media = []
|
251
|
-
self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
|
252
|
-
|
253
|
-
# Find the associated media record for the image
|
254
|
-
filename = File.basename(headers['location'])
|
255
|
-
m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
|
256
|
-
|
257
|
-
if m.nil?
|
258
|
-
self.log("Can't find media record for #{p.mls_acct} #{filename}.")
|
259
|
-
else
|
260
|
-
m.image = URI.parse(headers['location'])
|
261
|
-
media << m
|
262
|
-
#m.save
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
self.log("-- Uploading images to S3 for #{p.mls_acct}")
|
267
|
-
media.each do |m|
|
268
|
-
m.save
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def self.refresh_property_media(p)
|
273
|
-
self.log("-- Deleting images and metadata for #{p.mls_acct}...")
|
274
|
-
#CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
|
275
|
-
CabooseRets::Media.where(:mls_acct => p.mls_acct).destroy_all
|
276
|
-
|
277
|
-
self.log("-- Downloading image metadata for #{p.mls_acct}...")
|
239
|
+
|
240
|
+
self.log("- Downloading GFX records for #{p.mls_acct}...")
|
278
241
|
params = {
|
279
242
|
:search_type => 'Media',
|
280
|
-
:class => 'GFX',
|
281
|
-
#:query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
|
243
|
+
:class => 'GFX',
|
282
244
|
:query => "(MLS_ACCT=*#{p.id}*)",
|
283
245
|
:timeout => -1
|
284
246
|
}
|
247
|
+
ids = []
|
285
248
|
self.client.search(params) do |data|
|
286
|
-
|
287
|
-
m.
|
288
|
-
|
249
|
+
ids << data['MEDIA_ID']
|
250
|
+
m = CabooseRets::Media.where(:media_id => data['MEDIA_ID']).first
|
251
|
+
m = CabooseRets::Media.new if m.nil?
|
252
|
+
m.parse(data)
|
289
253
|
m.save
|
290
254
|
end
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
self.log "No image for #{agent.first_name} #{agent.last_name}."
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
def self.download_office_image(office)
|
306
|
-
self.log "Saving image for #{office.lo_name}..."
|
307
|
-
begin
|
308
|
-
self.client.get_object(:resource => :Office, :type => :Photo, :location => true, :id => office.lo_code) do |headers, content|
|
309
|
-
office.image = URI.parse(headers['location'])
|
310
|
-
office.save
|
311
|
-
end
|
312
|
-
rescue RETS::APIError => err
|
313
|
-
self.log "No image for #{office.lo_name}."
|
255
|
+
|
256
|
+
# Delete any records in the local database that shouldn't be there
|
257
|
+
puts "- Deleting GFX records for MLS ##{p.mls_acct} in the local database that are not in the remote database..."
|
258
|
+
query = "select media_id from rets_media where mls_acct = '#{p.mls_acct}'"
|
259
|
+
rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
260
|
+
local_ids = rows.collect{ |row| row['media_id'] }
|
261
|
+
ids_to_remove = local_ids - ids
|
262
|
+
if ids_to_remove && ids_to_remove.count > 0
|
263
|
+
query = ["delete from rets_media where media_id not in (?)", ids_to_remove]
|
264
|
+
ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
314
265
|
end
|
266
|
+
|
315
267
|
end
|
316
268
|
|
317
269
|
#=============================================================================
|
@@ -343,6 +295,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
343
295
|
end
|
344
296
|
|
345
297
|
def self.coords_from_address(address)
|
298
|
+
return false
|
346
299
|
begin
|
347
300
|
uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
|
348
301
|
uri.gsub!(" ", "+")
|
@@ -383,6 +336,78 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
383
336
|
def self.purge_helper(class_type, date_modified)
|
384
337
|
m = self.meta(class_type)
|
385
338
|
|
339
|
+
puts "Purging #{class_type}..."
|
340
|
+
|
341
|
+
# Get the total number of records
|
342
|
+
puts "- Getting total number of records for #{class_type}..."
|
343
|
+
params = {
|
344
|
+
:search_type => m.search_type,
|
345
|
+
:class => class_type,
|
346
|
+
:query => "(#{m.date_modified_field}=#{date_modified}T00:00:01+)",
|
347
|
+
:standard_names_only => true,
|
348
|
+
:timeout => -1
|
349
|
+
}
|
350
|
+
self.client.search(params.merge({ :count_mode => :only }))
|
351
|
+
count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
|
352
|
+
batch_count = (count.to_f/5000.0).ceil
|
353
|
+
|
354
|
+
ids = []
|
355
|
+
k = m.remote_key_field
|
356
|
+
(0...batch_count).each do |i|
|
357
|
+
puts "- Getting ids for #{class_type} (batch #{i+1} of #{batch_count})..."
|
358
|
+
self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
|
359
|
+
ids << case class_type
|
360
|
+
when 'RES' then data[k]
|
361
|
+
when 'COM' then data[k]
|
362
|
+
when 'LND' then data[k]
|
363
|
+
when 'MUL' then data[k]
|
364
|
+
when 'OFF' then data[k]
|
365
|
+
when 'AGT' then data[k]
|
366
|
+
when 'OPH' then data[k].to_i
|
367
|
+
when 'GFX' then data[k]
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
# Delete any records in the local database that shouldn't be there
|
373
|
+
puts "- Finding #{class_type} records in the local database that are not in the remote database..."
|
374
|
+
t = m.local_table
|
375
|
+
k = m.local_key_field
|
376
|
+
query = "select distinct #{k} from #{t}"
|
377
|
+
rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
378
|
+
local_ids = rows.collect{ |row| row[k] }
|
379
|
+
ids_to_remove = local_ids - ids
|
380
|
+
puts "- Found #{ids_to_remove.count} #{class_type} records in the local database that are not in the remote database."
|
381
|
+
puts "- Deleting #{class_type} records in the local database that shouldn't be there..."
|
382
|
+
query = ["delete from #{t} where #{k} not in (?)", ids_to_remove]
|
383
|
+
ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
384
|
+
|
385
|
+
# Find any ids in the remote database that should be in the local database
|
386
|
+
puts "- Finding #{class_type} records in the remote database that should be in the local database..."
|
387
|
+
query = "select distinct #{k} from #{t}"
|
388
|
+
rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
389
|
+
local_ids = rows.collect{ |row| row[k] }
|
390
|
+
ids_to_add = ids - local_ids
|
391
|
+
puts "- Found #{ids_to_add.count} #{class_type} records in the remote database that we need to add to the local database."
|
392
|
+
ids_to_add.each do |id|
|
393
|
+
puts "- Importing #{id}..."
|
394
|
+
case class_type
|
395
|
+
when 'RES' then self.delay.import_residential_property(id, false)
|
396
|
+
when 'COM' then self.delay.import_commercial_property(id, false)
|
397
|
+
when 'LND' then self.delay.import_land_property(id, false)
|
398
|
+
when 'MUL' then self.delay.import_multi_family_property(id, false)
|
399
|
+
when 'OFF' then self.delay.import_office(id, false)
|
400
|
+
when 'AGT' then self.delay.import_agent(id, false)
|
401
|
+
when 'OPH' then self.delay.import_open_house(id, false)
|
402
|
+
when 'GFX' then self.delay.import_media(id, false)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
end
|
407
|
+
|
408
|
+
def self.get_media_urls
|
409
|
+
m = self.meta(class_type)
|
410
|
+
|
386
411
|
# Get the total number of records
|
387
412
|
params = {
|
388
413
|
:search_type => m.search_type,
|
@@ -444,8 +469,8 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
444
469
|
#=============================================================================
|
445
470
|
|
446
471
|
def self.log(msg)
|
447
|
-
|
448
|
-
Rails.logger.info("[rets_importer] #{msg}")
|
472
|
+
puts "[rets_importer] #{msg}"
|
473
|
+
#Rails.logger.info("[rets_importer] #{msg}")
|
449
474
|
end
|
450
475
|
|
451
476
|
#=============================================================================
|
@@ -458,6 +483,9 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
458
483
|
|
459
484
|
begin
|
460
485
|
overlap = 30.seconds
|
486
|
+
puts DateTime.now
|
487
|
+
puts self.last_purged
|
488
|
+
puts (DateTime.now - self.last_purged)
|
461
489
|
if (DateTime.now - self.last_purged).to_i > 1
|
462
490
|
self.purge
|
463
491
|
self.save_last_purged(task_started)
|
@@ -0,0 +1,621 @@
|
|
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 => @@config['url'],
|
45
|
+
# :username => @@config['username'],
|
46
|
+
# :password => @@config['password']
|
47
|
+
# )
|
48
|
+
# end
|
49
|
+
# return @@rets_client
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def self.meta(class_type)
|
53
|
+
# case class_type
|
54
|
+
# when 'RES' then Caboose::StdClass.new({ :search_type => 'Property' , :remote_key_field => 'MLS_ACCT' , :local_key_field => 'mls_acct' , :local_table => 'rets_residential' , :date_modified_field => 'DATE_MODIFIED' })
|
55
|
+
# when 'COM' then Caboose::StdClass.new({ :search_type => 'Property' , :remote_key_field => 'MLS_ACCT' , :local_key_field => 'mls_acct' , :local_table => 'rets_commercial' , :date_modified_field => 'DATE_MODIFIED' })
|
56
|
+
# when 'LND' then Caboose::StdClass.new({ :search_type => 'Property' , :remote_key_field => 'MLS_ACCT' , :local_key_field => 'mls_acct' , :local_table => 'rets_land' , :date_modified_field => 'DATE_MODIFIED' })
|
57
|
+
# when 'MUL' then Caboose::StdClass.new({ :search_type => 'Property' , :remote_key_field => 'MLS_ACCT' , :local_key_field => 'mls_acct' , :local_table => 'rets_multi_family' , :date_modified_field => 'DATE_MODIFIED' })
|
58
|
+
# 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' })
|
59
|
+
# 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' })
|
60
|
+
# 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' })
|
61
|
+
# 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' })
|
62
|
+
# end
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# #=============================================================================
|
66
|
+
# # Import method
|
67
|
+
# #=============================================================================
|
68
|
+
#
|
69
|
+
# def self.import(class_type, query)
|
70
|
+
# m = self.meta(class_type)
|
71
|
+
# self.log("Importing #{m.search_type}:#{class_type} with query #{query}...")
|
72
|
+
# self.get_config if @@config.nil? || @@config['url'].nil?
|
73
|
+
# params = {
|
74
|
+
# :search_type => m.search_type,
|
75
|
+
# :class => class_type,
|
76
|
+
# :query => query,
|
77
|
+
# :limit => -1,
|
78
|
+
# :timeout => -1
|
79
|
+
# }
|
80
|
+
# obj = nil
|
81
|
+
# begin
|
82
|
+
# self.client.search(params) do |data|
|
83
|
+
# obj = self.get_instance_with_id(class_type, data)
|
84
|
+
# if obj.nil?
|
85
|
+
# self.log("Error: object is nil")
|
86
|
+
# self.log(data.inspect)
|
87
|
+
# next
|
88
|
+
# end
|
89
|
+
# obj.parse(data)
|
90
|
+
# obj.save
|
91
|
+
# end
|
92
|
+
# rescue RETS::HTTPError => err
|
93
|
+
# self.log "Import error for #{class_type}: #{query}"
|
94
|
+
# self.log err.message
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# def self.get_instance_with_id(class_type, data)
|
100
|
+
# obj = nil
|
101
|
+
# m = case class_type
|
102
|
+
# when 'OPH' then CabooseRets::OpenHouse
|
103
|
+
# when 'GFX' then CabooseRets::Media
|
104
|
+
# when 'COM' then CabooseRets::CommercialProperty
|
105
|
+
# when 'LND' then CabooseRets::LandProperty
|
106
|
+
# when 'MUL' then CabooseRets::MultiFamilyProperty
|
107
|
+
# when 'RES' then CabooseRets::ResidentialProperty
|
108
|
+
# when 'AGT' then CabooseRets::Agent
|
109
|
+
# when 'OFF' then CabooseRets::Office
|
110
|
+
# end
|
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_ACCT'].to_i ).exists? ? m.where(:id => data['MLS_ACCT'].to_i ).first : m.new(:id => data['MLS_ACCT'].to_i )
|
115
|
+
# when 'LND' then m.where(:id => data['MLS_ACCT'].to_i ).exists? ? m.where(:id => data['MLS_ACCT'].to_i ).first : m.new(:id => data['MLS_ACCT'].to_i )
|
116
|
+
# when 'MUL' then m.where(:id => data['MLS_ACCT'].to_i ).exists? ? m.where(:id => data['MLS_ACCT'].to_i ).first : m.new(:id => data['MLS_ACCT'].to_i )
|
117
|
+
# when 'RES' then m.where(:id => data['MLS_ACCT'].to_i ).exists? ? m.where(:id => data['MLS_ACCT'].to_i ).first : m.new(:id => data['MLS_ACCT'].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.update_helper('RES', date_modified, save_images)
|
130
|
+
# self.update_helper('COM', date_modified, save_images)
|
131
|
+
# self.update_helper('LND', date_modified, save_images)
|
132
|
+
# self.update_helper('MUL', date_modified, save_images)
|
133
|
+
# self.update_helper('OFF', date_modified, save_images)
|
134
|
+
# self.update_helper('AGT', date_modified, save_images)
|
135
|
+
# self.update_helper('OPH', date_modified, save_images)
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# def self.update_helper(class_type, date_modified, save_images = true)
|
139
|
+
# m = self.meta(class_type)
|
140
|
+
# k = m.remote_key_field
|
141
|
+
# params = {
|
142
|
+
# :search_type => m.search_type,
|
143
|
+
# :class => class_type,
|
144
|
+
# :select => [m.remote_key_field],
|
145
|
+
# :query => "(#{m.date_modified_field}=#{date_modified.strftime("%FT%T")}+)",
|
146
|
+
# :standard_names_only => true,
|
147
|
+
# :timeout => -1
|
148
|
+
# }
|
149
|
+
# self.client.search(params) do |data|
|
150
|
+
# case class_type
|
151
|
+
# when 'RES' then self.delay(:priority => 10).import_residential_property( data[k], save_images)
|
152
|
+
# when 'COM' then self.delay(:priority => 10).import_commercial_property( data[k], save_images)
|
153
|
+
# when 'LND' then self.delay(:priority => 10).import_land_property( data[k], save_images)
|
154
|
+
# when 'MUL' then self.delay(:priority => 10).import_multi_family_property( data[k], save_images)
|
155
|
+
# when 'OFF' then self.delay(:priority => 10).import_office( data[k], save_images)
|
156
|
+
# when 'AGT' then self.delay(:priority => 10).import_agent( data[k], save_images)
|
157
|
+
# when 'OPH' then self.delay(:priority => 10).import_open_house( data[k], save_images)
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# #=============================================================================
|
163
|
+
# # Single model import methods (called from a worker dyno)
|
164
|
+
# #=============================================================================
|
165
|
+
#
|
166
|
+
# def self.import_property(mls_acct, save_images = true)
|
167
|
+
# self.import('RES', "(MLS_ACCT=*#{mls_acct}*)")
|
168
|
+
# p = CabooseRets::ResidentialProperty.where(:id => mls_acct.to_i).first
|
169
|
+
# if p.nil?
|
170
|
+
# self.import('COM', "(MLS_ACCT=*#{mls_acct}*)")
|
171
|
+
# p = CabooseRets::CommercialProperty.where(:id => mls_acct.to_i).first
|
172
|
+
# if p.nil?
|
173
|
+
# self.import('LND', "(MLS_ACCT=*#{mls_acct}*)")
|
174
|
+
# p = CabooseRets::LandProperty.where(:id => mls_acct.to_i).first
|
175
|
+
# if p.nil?
|
176
|
+
# self.import('MUL', "(MLS_ACCT=*#{mls_acct}*)")
|
177
|
+
# p = CabooseRets::MultiFamilyProperty.where(:id => mls_acct.to_i).first
|
178
|
+
# return if p.nil?
|
179
|
+
# end
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
# self.download_property_images(p, save_images)
|
183
|
+
# end
|
184
|
+
#
|
185
|
+
# def self.import_residential_property(mls_acct, save_images = true)
|
186
|
+
# self.import('RES', "(MLS_ACCT=*#{mls_acct}*)")
|
187
|
+
# p = CabooseRets::ResidentialProperty.where(:id => mls_acct.to_i).first
|
188
|
+
# self.download_property_images(p, save_images)
|
189
|
+
# self.update_coords(p)
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# def self.import_commercial_property(mls_acct, save_images = true)
|
193
|
+
# self.import('COM', "(MLS_ACCT=*#{mls_acct}*)")
|
194
|
+
# p = CabooseRets::CommercialProperty.where(:id => mls_acct.to_i).first
|
195
|
+
# self.download_property_images(p, save_images)
|
196
|
+
# self.update_coords(p)
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# def self.import_land_property(mls_acct, save_images = true)
|
200
|
+
# self.import('LND', "(MLS_ACCT=*#{mls_acct}*)")
|
201
|
+
# p = CabooseRets::LandProperty.where(:id => mls_acct.to_i).first
|
202
|
+
# self.download_property_images(p, save_images)
|
203
|
+
# self.update_coords(p)
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
# def self.import_multi_family_property(mls_acct, save_images = true)
|
207
|
+
# self.import('MUL', "(MLS_ACCT=*#{mls_acct}*)")
|
208
|
+
# p = CabooseRets::MultiFamilyProperty.where(:id => mls_acct.to_i).first
|
209
|
+
# self.download_property_images(p, save_images)
|
210
|
+
# self.update_coords(p)
|
211
|
+
# end
|
212
|
+
#
|
213
|
+
# def self.import_office(lo_code, save_images = true)
|
214
|
+
# self.import('OFF', "(LO_LO_CODE=*#{lo_code}*)")
|
215
|
+
# office = CabooseRets::Office.where(:lo_code => lo_code.to_s).first
|
216
|
+
# self.download_office_image(office) if save_images == true
|
217
|
+
# end
|
218
|
+
#
|
219
|
+
# def self.import_agent(la_code, save_images = true)
|
220
|
+
# self.import('AGT', "(LA_LA_CODE=*#{la_code}*)")
|
221
|
+
# a = CabooseRets::Agent.where(:la_code => la_code.to_s).first
|
222
|
+
# self.download_agent_image(a) if save_images == true
|
223
|
+
# end
|
224
|
+
#
|
225
|
+
# def self.import_open_house(id, save_images = true)
|
226
|
+
# self.import('OPH', "((ID=#{id}+),(ID=#{id}-))")
|
227
|
+
# end
|
228
|
+
#
|
229
|
+
# def self.import_media(id, save_images = true)
|
230
|
+
# self.import('GFX', "((MEDIA_ID=#{id}+),(MEDIA_ID=#{id}-))")
|
231
|
+
# #m = CabooseRets::Media.where(:media_id => id.to_s).first
|
232
|
+
# #if m.nil?
|
233
|
+
# # self.log("Can't find media record for #{id}.")
|
234
|
+
# # return
|
235
|
+
# #end
|
236
|
+
# #self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => m.mls_acct) do |headers, content|
|
237
|
+
# # if headers['object-id'].to_i == m.media_order
|
238
|
+
# # m.url = headers['location']
|
239
|
+
# # #m.image = URI.parse(headers['location'])
|
240
|
+
# # end
|
241
|
+
# #end
|
242
|
+
# #m.save
|
243
|
+
# end
|
244
|
+
#
|
245
|
+
# #=============================================================================
|
246
|
+
# # Images
|
247
|
+
# #=============================================================================
|
248
|
+
#
|
249
|
+
# def self.download_property_images(p, save_images = true)
|
250
|
+
# return if save_images == false
|
251
|
+
# self.refresh_property_media(p)
|
252
|
+
#
|
253
|
+
# #self.log("-- Downloading images and resizing for #{p.mls_acct}")
|
254
|
+
# #media = []
|
255
|
+
# #self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
|
256
|
+
# #
|
257
|
+
# # # Find the associated media record for the image
|
258
|
+
# # #filename = File.basename(headers['location'])
|
259
|
+
# # #m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
|
260
|
+
# # m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_order => headers['object-id'].to_i).first
|
261
|
+
# #
|
262
|
+
# # if m.nil?
|
263
|
+
# # self.log("Can't find media record for #{p.mls_acct} #{filename}.")
|
264
|
+
# # else
|
265
|
+
# # m.url = headers['location']
|
266
|
+
# # #m.image = URI.parse(headers['location'])
|
267
|
+
# # media << m
|
268
|
+
# # #m.save
|
269
|
+
# # end
|
270
|
+
# #end
|
271
|
+
# #
|
272
|
+
# #self.log("-- Uploading images to S3 for #{p.mls_acct}")
|
273
|
+
# #media.each do |m|
|
274
|
+
# # m.save
|
275
|
+
# #end
|
276
|
+
# end
|
277
|
+
#
|
278
|
+
# def self.refresh_property_media(p)
|
279
|
+
# #self.log("-- Deleting images and metadata for #{p.mls_acct}...")
|
280
|
+
# #CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
|
281
|
+
# #CabooseRets::Media.where(:mls_acct => p.mls_acct).destroy_all
|
282
|
+
#
|
283
|
+
# self.log("-- Downloading GFX records for #{p.mls_acct}...")
|
284
|
+
# params = {
|
285
|
+
# :search_type => 'Media',
|
286
|
+
# :class => 'GFX',
|
287
|
+
# :query => "(MLS_ACCT=*#{p.id}*)",
|
288
|
+
# :timeout => -1
|
289
|
+
# }
|
290
|
+
# ids = []
|
291
|
+
# self.client.search(params) do |data|
|
292
|
+
# ids << data['MEDIA_ID']
|
293
|
+
# m = CabooseRets::Media.new
|
294
|
+
# m.parse(data)
|
295
|
+
# m.save
|
296
|
+
# end
|
297
|
+
#
|
298
|
+
# # Delete any records in the local database that shouldn't be there
|
299
|
+
# puts "- Finding GFX records for MLS ##{p.mls_acct} in the local database that are not in the remote database..."
|
300
|
+
# query = "select media_id from rets_media where mls_acct = '#{p.mls_acct}'"
|
301
|
+
# rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
302
|
+
# local_ids = rows.collect{ |row| row[k] }
|
303
|
+
# ids_to_remove = local_ids - ids
|
304
|
+
# if ids_to_remove && ids_to_remove > 0
|
305
|
+
# query = ["delete from rets_media where media_id not in (?)", ids_to_remove]
|
306
|
+
# ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
307
|
+
# end
|
308
|
+
#
|
309
|
+
# end
|
310
|
+
#
|
311
|
+
# #def self.download_agent_image(agent)
|
312
|
+
# # self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
|
313
|
+
# # begin
|
314
|
+
# # self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => agent.la_code) do |headers, content|
|
315
|
+
# # puts headers.inspect
|
316
|
+
# # agent.image = URI.parse(headers['location'])
|
317
|
+
# # agent.save
|
318
|
+
# # end
|
319
|
+
# # rescue RETS::APIError => err
|
320
|
+
# # self.log "No image for #{agent.first_name} #{agent.last_name}."
|
321
|
+
# # end
|
322
|
+
# #end
|
323
|
+
#
|
324
|
+
# #def self.download_office_image(office)
|
325
|
+
# # self.log "Saving image for #{office.lo_name}..."
|
326
|
+
# # begin
|
327
|
+
# # self.client.get_object(:resource => :Office, :type => :Photo, :location => true, :id => office.lo_code) do |headers, content|
|
328
|
+
# # office.image = URI.parse(headers['location'])
|
329
|
+
# # office.save
|
330
|
+
# # end
|
331
|
+
# # rescue RETS::APIError => err
|
332
|
+
# # self.log "No image for #{office.lo_name}."
|
333
|
+
# # end
|
334
|
+
# #end
|
335
|
+
#
|
336
|
+
# #=============================================================================
|
337
|
+
# # GPS
|
338
|
+
# #=============================================================================
|
339
|
+
#
|
340
|
+
# def self.update_coords(p = nil)
|
341
|
+
# if p.nil?
|
342
|
+
# models = [CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty]
|
343
|
+
# names = ["commercial", "land", "multi-family", "residential"]
|
344
|
+
# i = 0
|
345
|
+
# models.each do |model|
|
346
|
+
# self.log "Updating coords #{names[i]} properties..."
|
347
|
+
# model.where(:latitude => nil).reorder(:mls_acct).each do |p|
|
348
|
+
# self.update_coords(p)
|
349
|
+
# end
|
350
|
+
# i = i + 1
|
351
|
+
# end
|
352
|
+
# return
|
353
|
+
# end
|
354
|
+
#
|
355
|
+
# self.log "Getting coords for mls_acct #{p.mls_acct}..."
|
356
|
+
# coords = self.coords_from_address(CGI::escape "#{p.street_num} #{p.street_name}, #{p.city}, #{p.state} #{p.zip}")
|
357
|
+
# return if coords.nil? || coords == false
|
358
|
+
#
|
359
|
+
# p.latitude = coords['lat']
|
360
|
+
# p.longitude = coords['lng']
|
361
|
+
# p.save
|
362
|
+
# end
|
363
|
+
#
|
364
|
+
# def self.coords_from_address(address)
|
365
|
+
# return false
|
366
|
+
# begin
|
367
|
+
# uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
|
368
|
+
# uri.gsub!(" ", "+")
|
369
|
+
# resp = HTTParty.get(uri)
|
370
|
+
# json = JSON.parse(resp.body)
|
371
|
+
# return json['results'][0]['geometry']['location']
|
372
|
+
# rescue
|
373
|
+
# self.log "Error: #{uri}"
|
374
|
+
# sleep(2)
|
375
|
+
# return false
|
376
|
+
# end
|
377
|
+
# end
|
378
|
+
#
|
379
|
+
# #=============================================================================
|
380
|
+
# # Purging
|
381
|
+
# #=============================================================================
|
382
|
+
#
|
383
|
+
# def self.purge
|
384
|
+
# self.purge_residential
|
385
|
+
# self.purge_commercial
|
386
|
+
# self.purge_land
|
387
|
+
# self.purge_multi_family
|
388
|
+
# self.purge_offices
|
389
|
+
# self.purge_agents
|
390
|
+
# self.purge_open_houses
|
391
|
+
# self.purge_media
|
392
|
+
# end
|
393
|
+
#
|
394
|
+
# def self.purge_residential() self.purge_helper('RES', '2012-01-01') end
|
395
|
+
# def self.purge_commercial() self.purge_helper('COM', '2012-01-01') end
|
396
|
+
# def self.purge_land() self.purge_helper('LND', '2012-01-01') end
|
397
|
+
# def self.purge_multi_family() self.purge_helper('MUL', '2012-01-01') end
|
398
|
+
# def self.purge_offices() self.purge_helper('OFF', '2012-01-01') end
|
399
|
+
# def self.purge_agents() self.purge_helper('AGT', '2012-01-01') end
|
400
|
+
# def self.purge_open_houses() self.purge_helper('OPH', '2012-01-01') end
|
401
|
+
# def self.purge_media() self.purge_helper('GFX', '2012-01-01') end
|
402
|
+
#
|
403
|
+
# def self.purge_helper(class_type, date_modified)
|
404
|
+
# m = self.meta(class_type)
|
405
|
+
#
|
406
|
+
# puts "Purging #{class_type}..."
|
407
|
+
#
|
408
|
+
# # Get the total number of records
|
409
|
+
# puts "- Getting total number of records for #{class_type}..."
|
410
|
+
# params = {
|
411
|
+
# :search_type => m.search_type,
|
412
|
+
# :class => class_type,
|
413
|
+
# :query => "(#{m.date_modified_field}=#{date_modified}T00:00:01+)",
|
414
|
+
# :standard_names_only => true,
|
415
|
+
# :timeout => -1
|
416
|
+
# }
|
417
|
+
# self.client.search(params.merge({ :count_mode => :only }))
|
418
|
+
# count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
|
419
|
+
# batch_count = (count.to_f/5000.0).ceil
|
420
|
+
#
|
421
|
+
# ids = []
|
422
|
+
# k = m.remote_key_field
|
423
|
+
# (0...batch_count).each do |i|
|
424
|
+
# puts "- Getting ids for #{class_type} (batch #{i+1} of #{batch_count})..."
|
425
|
+
# self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
|
426
|
+
# ids << case class_type
|
427
|
+
# when 'RES' then data[k]
|
428
|
+
# when 'COM' then data[k]
|
429
|
+
# when 'LND' then data[k]
|
430
|
+
# when 'MUL' then data[k]
|
431
|
+
# when 'OFF' then data[k]
|
432
|
+
# when 'AGT' then data[k]
|
433
|
+
# when 'OPH' then data[k].to_i
|
434
|
+
# when 'GFX' then data[k]
|
435
|
+
# end
|
436
|
+
# end
|
437
|
+
# end
|
438
|
+
#
|
439
|
+
# # Delete any records in the local database that shouldn't be there
|
440
|
+
# puts "- Finding #{class_type} records in the local database that are not in the remote database..."
|
441
|
+
# t = m.local_table
|
442
|
+
# k = m.local_key_field
|
443
|
+
# query = "select distinct #{k} from #{t}"
|
444
|
+
# rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
445
|
+
# local_ids = rows.collect{ |row| row[k] }
|
446
|
+
# ids_to_remove = local_ids - ids
|
447
|
+
# puts "- Found #{ids_to_remove.count} #{class_type} records in the local database that are not in the remote database."
|
448
|
+
# puts "- Deleting #{class_type} records in the local database that shouldn't be there..."
|
449
|
+
# query = ["delete from #{t} where #{k} not in (?)", ids_to_remove]
|
450
|
+
# ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
451
|
+
#
|
452
|
+
# # Find any ids in the remote database that should be in the local database
|
453
|
+
# puts "- Finding #{class_type} records in the remote database that should be in the local database..."
|
454
|
+
# query = "select distinct #{k} from #{t}"
|
455
|
+
# rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
456
|
+
# local_ids = rows.collect{ |row| row[k] }
|
457
|
+
# ids_to_add = ids - local_ids
|
458
|
+
# puts "- Found #{ids_to_add.count} #{class_type} records in the remote database that we need to add to the local database."
|
459
|
+
# ids_to_add.each do |id|
|
460
|
+
# puts "- Importing #{id}..."
|
461
|
+
# case class_type
|
462
|
+
# when 'RES' then self.delay.import_residential_property(id, false)
|
463
|
+
# when 'COM' then self.delay.import_commercial_property(id, false)
|
464
|
+
# when 'LND' then self.delay.import_land_property(id, false)
|
465
|
+
# when 'MUL' then self.delay.import_multi_family_property(id, false)
|
466
|
+
# when 'OFF' then self.delay.import_office(id, false)
|
467
|
+
# when 'AGT' then self.delay.import_agent(id, false)
|
468
|
+
# when 'OPH' then self.delay.import_open_house(id, false)
|
469
|
+
# when 'GFX' then self.delay.import_media(id, false)
|
470
|
+
# end
|
471
|
+
# end
|
472
|
+
#
|
473
|
+
# end
|
474
|
+
#
|
475
|
+
# def self.get_media_urls
|
476
|
+
# m = self.meta(class_type)
|
477
|
+
#
|
478
|
+
# # Get the total number of records
|
479
|
+
# params = {
|
480
|
+
# :search_type => m.search_type,
|
481
|
+
# :class => class_type,
|
482
|
+
# :query => "(#{m.date_modified_field}=#{date_modified}T00:00:01+)",
|
483
|
+
# :standard_names_only => true,
|
484
|
+
# :timeout => -1
|
485
|
+
# }
|
486
|
+
# self.client.search(params.merge({ :count_mode => :only }))
|
487
|
+
# count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
|
488
|
+
# batch_count = (count.to_f/5000.0).ceil
|
489
|
+
#
|
490
|
+
# ids = []
|
491
|
+
# k = m.remote_key_field
|
492
|
+
# (0...batch_count).each do |i|
|
493
|
+
# self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
|
494
|
+
# ids << case class_type
|
495
|
+
# when 'RES' then data[k]
|
496
|
+
# when 'COM' then data[k]
|
497
|
+
# when 'LND' then data[k]
|
498
|
+
# when 'MUL' then data[k]
|
499
|
+
# when 'OFF' then data[k]
|
500
|
+
# when 'AGT' then data[k]
|
501
|
+
# when 'OPH' then data[k].to_i
|
502
|
+
# when 'GFX' then data[k]
|
503
|
+
# end
|
504
|
+
# end
|
505
|
+
# end
|
506
|
+
#
|
507
|
+
# # Delete any records in the local database that shouldn't be there
|
508
|
+
# t = m.local_table
|
509
|
+
# k = m.local_key_field
|
510
|
+
# query = ["delete from #{t} where #{k} not in (?)", ids]
|
511
|
+
# ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
512
|
+
#
|
513
|
+
# # Find any ids in the remote database that should be in the local database
|
514
|
+
# query = "select distinct #{k} from #{t}"
|
515
|
+
# rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
516
|
+
# local_ids = rows.collect{ |row| row[k] }
|
517
|
+
# ids_to_add = ids - local_ids
|
518
|
+
# ids_to_add.each do |id|
|
519
|
+
# puts "Importing #{id}..."
|
520
|
+
# case class_type
|
521
|
+
# when 'RES' then self.delay.import_residential_property(id, false)
|
522
|
+
# when 'COM' then self.delay.import_commercial_property(id, false)
|
523
|
+
# when 'LND' then self.delay.import_land_property(id, false)
|
524
|
+
# when 'MUL' then self.delay.import_multi_family_property(id, false)
|
525
|
+
# when 'OFF' then self.delay.import_office(id, false)
|
526
|
+
# when 'AGT' then self.delay.import_agent(id, false)
|
527
|
+
# when 'OPH' then self.delay.import_open_house(id, false)
|
528
|
+
# when 'GFX' then self.delay.import_media(id)
|
529
|
+
# end
|
530
|
+
# end
|
531
|
+
#
|
532
|
+
# end
|
533
|
+
#
|
534
|
+
# #=============================================================================
|
535
|
+
# # Logging
|
536
|
+
# #=============================================================================
|
537
|
+
#
|
538
|
+
# def self.log(msg)
|
539
|
+
# puts "[rets_importer] #{msg}"
|
540
|
+
# #Rails.logger.info("[rets_importer] #{msg}")
|
541
|
+
# end
|
542
|
+
#
|
543
|
+
# #=============================================================================
|
544
|
+
# # Locking update task
|
545
|
+
# #=============================================================================
|
546
|
+
#
|
547
|
+
# def self.update_rets
|
548
|
+
# return if self.task_is_locked
|
549
|
+
# task_started = self.lock_task
|
550
|
+
#
|
551
|
+
# begin
|
552
|
+
# overlap = 30.seconds
|
553
|
+
# puts DateTime.now
|
554
|
+
# puts self.last_purged
|
555
|
+
# puts (DateTime.now - self.last_purged)
|
556
|
+
# if (DateTime.now - self.last_purged).to_i > 1
|
557
|
+
# self.purge
|
558
|
+
# self.save_last_purged(task_started)
|
559
|
+
# #overlap = 1.month
|
560
|
+
# end
|
561
|
+
# self.update_after(self.last_updated - overlap)
|
562
|
+
# self.save_last_updated(task_started)
|
563
|
+
# self.unlock_task
|
564
|
+
# rescue
|
565
|
+
# raise
|
566
|
+
# ensure
|
567
|
+
# self.unlock_task_if_last_updated(task_started)
|
568
|
+
# end
|
569
|
+
#
|
570
|
+
# # Start the same update process in five minutes
|
571
|
+
# self.delay(:run_at => 1.minutes.from_now).update_rets
|
572
|
+
# end
|
573
|
+
#
|
574
|
+
# def self.last_updated
|
575
|
+
# if !Caboose::Setting.exists?(:name => 'rets_last_updated')
|
576
|
+
# Caboose::Setting.create(:name => 'rets_last_updated', :value => '2013-08-06T00:00:01')
|
577
|
+
# end
|
578
|
+
# s = Caboose::Setting.where(:name => 'rets_last_updated').first
|
579
|
+
# return DateTime.parse(s.value)
|
580
|
+
# end
|
581
|
+
#
|
582
|
+
# def self.last_purged
|
583
|
+
# if !Caboose::Setting.exists?(:name => 'rets_last_purged')
|
584
|
+
# Caboose::Setting.create(:name => 'rets_last_purged', :value => '2013-08-06T00:00:01')
|
585
|
+
# end
|
586
|
+
# s = Caboose::Setting.where(:name => 'rets_last_purged').first
|
587
|
+
# return DateTime.parse(s.value)
|
588
|
+
# end
|
589
|
+
#
|
590
|
+
# def self.save_last_updated(d)
|
591
|
+
# s = Caboose::Setting.where(:name => 'rets_last_updated').first
|
592
|
+
# s.value = d.strftime('%FT%T')
|
593
|
+
# s.save
|
594
|
+
# end
|
595
|
+
#
|
596
|
+
# def self.save_last_purged(d)
|
597
|
+
# s = Caboose::Setting.where(:name => 'rets_last_purged').first
|
598
|
+
# s.value = d.strftime('%FT%T')
|
599
|
+
# s.save
|
600
|
+
# end
|
601
|
+
#
|
602
|
+
# def self.task_is_locked
|
603
|
+
# return Caboose::Setting.exists?(:name => 'rets_update_running')
|
604
|
+
# end
|
605
|
+
#
|
606
|
+
# def self.lock_task
|
607
|
+
# d = DateTime.now.utc - 5.hours
|
608
|
+
# Caboose::Setting.create(:name => 'rets_update_running', :value => d.strftime('%F %T'))
|
609
|
+
# return d
|
610
|
+
# end
|
611
|
+
#
|
612
|
+
# def self.unlock_task
|
613
|
+
# Caboose::Setting.where(:name => 'rets_update_running').first.destroy
|
614
|
+
# end
|
615
|
+
#
|
616
|
+
# def self.unlock_task_if_last_updated(d)
|
617
|
+
# setting = Caboose::Setting.where(:name => 'rets_update_running').first
|
618
|
+
# self.unlock_task if setting && d.strftime('%F %T') == setting.value
|
619
|
+
# end
|
620
|
+
#
|
621
|
+
#end
|
@@ -9,6 +9,12 @@ class CabooseRets::Schema < Caboose::Utilities::Schema
|
|
9
9
|
}
|
10
10
|
end
|
11
11
|
|
12
|
+
def self.indexes
|
13
|
+
{
|
14
|
+
CabooseRets::Media => [:media_id]
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
12
18
|
# The schema of the database
|
13
19
|
# { Model => [[name, data_type, options]] }
|
14
20
|
def self.schema
|
@@ -377,10 +383,10 @@ class CabooseRets::Schema < Caboose::Utilities::Schema
|
|
377
383
|
[ :file_name , :string ],
|
378
384
|
[ :media_id , :string ],
|
379
385
|
[ :media_order , :integer, { :default => 0 }],
|
380
|
-
[ :media_remarks , :text
|
386
|
+
[ :media_remarks , :text ],
|
381
387
|
[ :media_type , :string ],
|
382
388
|
[ :mls_acct , :string ],
|
383
|
-
[ :url , :text
|
389
|
+
[ :url , :text ]
|
384
390
|
],
|
385
391
|
CabooseRets::MultiFamilyProperty => [
|
386
392
|
[ :acreage , :text ],
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<% @properties.each do |p| %>
|
10
10
|
<li>
|
11
11
|
<% if p.images && p.images.count > 0 %>
|
12
|
-
<div class='image'><a href="/residential/<%= p.mls_acct %>/details"><img src="<%= p.images[0].
|
12
|
+
<div class='image'><a href="/residential/<%= p.mls_acct %>/details"><img src="<%= p.images[0].image_url(:thumb) %>" /></a></div>
|
13
13
|
<% end %>
|
14
14
|
<div class="address"><% if !p.unit_num.nil? && p.unit_num.strip.length > 0 %>Unit <%= p.unit_num %>, <% end %><%= p.street_num %> <%= p.street_name.titleize %></div>
|
15
15
|
<% if p.agent %>
|
data/lib/caboose-rets.rb
CHANGED
@@ -4,5 +4,17 @@ module CabooseRets
|
|
4
4
|
|
5
5
|
mattr_accessor :default_property_sort
|
6
6
|
@@default_property_sort = 'current_price DESC, mls_acct'
|
7
|
-
|
7
|
+
|
8
|
+
mattr_accessor :use_hosted_images
|
9
|
+
@@use_hosted_images = true
|
10
|
+
|
11
|
+
mattr_accessor :media_base_url
|
12
|
+
@@media_base_url = ''
|
13
|
+
|
14
|
+
mattr_accessor :agents_base_url
|
15
|
+
@@agents_base_url = ''
|
16
|
+
|
17
|
+
mattr_accessor :offices_base_url
|
18
|
+
@@offices_base_url = ''
|
19
|
+
|
8
20
|
end
|
data/lib/caboose_rets/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caboose-rets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.70
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Barry
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- app/models/caboose_rets/open_house.rb
|
59
59
|
- app/models/caboose_rets/residential_property.rb
|
60
60
|
- app/models/caboose_rets/rets_importer.rb
|
61
|
+
- app/models/caboose_rets/rets_importer_bak.rb
|
61
62
|
- app/models/caboose_rets/rets_plugin.rb
|
62
63
|
- app/models/caboose_rets/saved_property.rb
|
63
64
|
- app/models/caboose_rets/saved_search.rb
|