caboose-rets 0.0.69 → 0.0.70
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.
- 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
|