caboose-rets 0.0.52 → 0.0.53

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NzFmZTA4NTZmNTY4Nzg4NWU5MTYzZWRjMzFhMGQ0MzQ2Zjk3MjMwYg==
4
+ MTBjMzMwZDYzNDkzMTQ3M2U3NTdkMjQ4MDc4OTZmMzk4YjlhM2Q2Yg==
5
5
  data.tar.gz: !binary |-
6
- N2FmZDFjOTBmZmFhMjk0ZmM3NmFiZWM2NGFlOWE4MGQzYTJkNzc4Zg==
6
+ NmYyMWM1YmRjYjUwZjg0NWMxODk1NGVmNDUwMzQyMjBjZGJlNTFmZg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MGIwM2M3NWI3YzAyN2MyMzczODM2MzRiYWI2NzNjZjIwOGU0MzI5M2ZhYzk1
10
- OTgwYjdjYTdkNTQyOTk3YzQ4YzJlZDA1ZjgxNTQ0NDkzYjk5MjViZjQ0Nzk0
11
- MWY2MjllN2QyMzNiYmJiODdkNzA2YmM4NWUzOGNlNWY0MDg1MmM=
9
+ ZDQ4NWYwYjQ3MGU5NTFlZWRlM2ZmMWEwZjhkODllN2QwZDRjN2FiMmNlZjBk
10
+ MGIxNDNhOGY3YmRjYzUwMzY4MTAzZDQzNDE0ZTE0ZjVhZjgxNWI2NmY5YTU2
11
+ MjI1MDVhNmVmNTVkMGZjMGZiMzM0ZWNkNDgwZWQxZWFhODQwODg=
12
12
  data.tar.gz: !binary |-
13
- YzcyNDJlNTc1OWQxZDY3YjkzMThkNjZjMzk2YzhjN2Q4NzlmMzkxNzAwYWVh
14
- YWE1MDUzYWFmZDVjMzZmN2FhNjc2Mzc1OGVmOWI4YzkxMjQ4OWYxZGNhMzA1
15
- NDFhZmQ1YjVhYjI0MGNhOTU3NjJmMzEwYmZhNDFmYmYyZWJhMzY=
13
+ OGJmNTRiZjE3ZjUzYjE0ODFmNTg4ODY1YTllZGQ2MzQyYTVkMmQ3MjFjNGZl
14
+ ZGFhYzAyYWVjNGNkM2UxY2NiYjIyN2Y4OTRjZDZlODkxZWYwZmRiZWY3Nzkz
15
+ ZmIwNjJmZmY5MzFlOTg2YTc0OTRhYjRiODcyOGM1MGIzYTczNWY=
@@ -110,11 +110,9 @@ module CabooseRets
110
110
  # GET /admin/residential/:mls_acct/refresh
111
111
  def admin_refresh
112
112
  return if !user_is_allowed('properties', 'edit')
113
-
113
+
114
114
  p = ResidentialProperty.find(params[:mls_acct])
115
- p.delay.refresh_from_mls
116
- #RetsImporter.import("(MLS_ACCT=#{p.mls_acct})", 'Property', 'RES')
117
- #RetsImporter.download_property_images(p)
115
+ p.delay.refresh_from_mls
118
116
 
119
117
  resp = Caboose::StdClass.new
120
118
  resp.success = "The property's info is being updated from MLS. This may take a few minutes depending on how many images it has."
@@ -12,8 +12,8 @@ module CabooseRets
12
12
  def admin_import
13
13
  return if !user_is_allowed('properties', 'edit')
14
14
 
15
- mls_acct = params[:mls_acct].to_i
16
- ResidentialProperty.delay.import_from_mls(mls_acct)
15
+ mls_acct = params[:mls_acct].to_i
16
+ CabooseRets::RetsImporter.delay.import_property(mls_acct)
17
17
 
18
18
  resp = Caboose::StdClass.new
19
19
  resp.success = "The property is being imported from MLS. This may take a few minutes depending on how many images it has."
@@ -30,6 +30,16 @@ class CabooseRets::Agent < ActiveRecord::Base
30
30
  self.last_name[2] = self.last_name[2].upcase
31
31
  end
32
32
  end
33
+
34
+ def refresh_from_mls
35
+ CabooseRets::RetsImporter.import("(MLS_ACCT=#{self.mls_acct})", 'Property', 'RES')
36
+ CabooseRets::RetsImporter.download_property_images(self)
37
+ end
38
+
39
+ def self.refresh_from_mls(la_code)
40
+ CabooseRets::RetsImporter.import("(LA_LA_CODE=#{la_code})", 'Agent', 'AGT')
41
+ CabooseRets::RetsImporter.import_property(mls_acct)
42
+ end
33
43
 
34
44
  def parse(data)
35
45
  self.beeper_phone = data['LA_BEEPER_PHONE']
@@ -14,16 +14,11 @@ class CabooseRets::CommercialProperty < ActiveRecord::Base
14
14
  return media.url
15
15
  end
16
16
  def self.geolocatable() all(conditions: "latitude IS NOT NULL AND longitude IS NOT NULL") end
17
-
18
- def refresh_from_mls
19
- CabooseRets::RetsImporter.import("(MLS_ACCT=#{self.mls_acct})", 'Property', 'COM')
20
- CabooseRets::RetsImporter.download_property_images(self)
21
- end
22
17
 
23
- def self.import_from_mls(mls_acct)
24
- CabooseRets::RetsImporter.import_property(mls_acct)
18
+ def refresh_from_mls
19
+ CabooseRets::RetsImporter.import_commercial_property(self.mls_acct)
25
20
  end
26
-
21
+
27
22
  def parse(data)
28
23
  self.acreage = data['ACREAGE']
29
24
  self.adjoining_land_use = data['ADJOINING_LAND_USE']
@@ -15,13 +15,8 @@ class CabooseRets::LandProperty < ActiveRecord::Base
15
15
  end
16
16
  def self.geolocatable() all(conditions: "latitude IS NOT NULL AND longitude IS NOT NULL") end
17
17
 
18
- def refresh_from_mls
19
- CabooseRets::RetsImporter.import("(MLS_ACCT=#{self.mls_acct})", 'Property', 'LND')
20
- CabooseRets::RetsImporter.download_property_images(self)
21
- end
22
-
23
- def self.import_from_mls(mls_acct)
24
- CabooseRets::RetsImporter.import_property(mls_acct)
18
+ def refresh_from_mls
19
+ CabooseRets::RetsImporter.import_land_property(self.mls_acct)
25
20
  end
26
21
 
27
22
  def parse(data)
@@ -16,12 +16,7 @@ class CabooseRets::MultiFamilyProperty < ActiveRecord::Base
16
16
  def self.geolocatable() all(conditions: "latitude IS NOT NULL AND longitude IS NOT NULL") end
17
17
 
18
18
  def refresh_from_mls
19
- CabooseRets::RetsImporter.import("(MLS_ACCT=#{self.mls_acct})", 'Property', 'MUL')
20
- CabooseRets::RetsImporter.download_property_images(self)
21
- end
22
-
23
- def self.import_from_mls(mls_acct)
24
- CabooseRets::RetsImporter.import_property(mls_acct)
19
+ CabooseRets::RetsImporter.import_multi_family_property(self.mls_acct)
25
20
  end
26
21
 
27
22
  def parse(data)
@@ -1,6 +1,13 @@
1
1
 
2
2
  class CabooseRets::Office < ActiveRecord::Base
3
3
  self.table_name = "rets_offices"
4
+ has_attached_file :image,
5
+ :path => 'rets/offices/:lo_code_:style.:extension',
6
+ :styles => {
7
+ :thumb => '100x150>',
8
+ :large => '200x300>'
9
+ }
10
+ do_not_validate_attachment_file_type :image
4
11
  attr_accessible :id, :name, :lo_code
5
12
 
6
13
  def parse(data)
@@ -16,14 +16,9 @@ class CabooseRets::ResidentialProperty < ActiveRecord::Base
16
16
  def self.geolocatable() all(conditions: "latitude IS NOT NULL AND longitude IS NOT NULL") end
17
17
 
18
18
  def refresh_from_mls
19
- CabooseRets::RetsImporter.import("(MLS_ACCT=#{self.mls_acct})", 'Property', 'RES')
20
- CabooseRets::RetsImporter.download_property_images(self)
19
+ CabooseRets::RetsImporter.import_residential_property(self.mls_acct)
21
20
  end
22
-
23
- def self.import_from_mls(mls_acct)
24
- CabooseRets::RetsImporter.import_property(mls_acct)
25
- end
26
-
21
+
27
22
  #=============================================================================
28
23
 
29
24
  # Assume this is running in a worker dyno
@@ -8,41 +8,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
8
8
 
9
9
  @@rets_client = nil
10
10
  @@config = nil
11
- @@object_types = {
12
- 'OpenHouse' => ['OPH'],
13
- 'Media' => ['GFX'],
14
- 'Property' => ['COM', 'LND', 'MUL', 'RES'],
15
- 'Agent' => ['AGT'],
16
- 'Office' => ['OFF']
17
- }
18
- @@key_fields = {
19
- 'OpenHouse' => 'ID',
20
- 'Media' => 'MEDIA_ID',
21
- 'Property' => 'MLS_ACCT',
22
- 'Agent' => 'LA_LA_CODE',
23
- 'Office' => 'LO_LO_CODE'
24
- }
25
- @@models = {
26
- 'OPH' => 'CabooseRets::OpenHouse',
27
- 'GFX' => 'CabooseRets::Media',
28
- 'COM' => 'CabooseRets::CommercialProperty',
29
- 'LND' => 'CabooseRets::LandProperty',
30
- 'MUL' => 'CabooseRets::MultiFamilyProperty',
31
- 'RES' => 'CabooseRets::ResidentialProperty',
32
- 'AGT' => 'CabooseRets::Agent',
33
- 'OFF' => 'CabooseRets::Office'
34
- }
35
- @@date_modified_fields = {
36
- 'OPH' => 'DATE_MODIFIED',
37
- 'GFX' => 'DATE_MODIFIED',
38
- 'COM' => 'DATE_MODIFIED',
39
- 'LND' => 'DATE_MODIFIED',
40
- 'MUL' => 'DATE_MODIFIED',
41
- 'RES' => 'DATE_MODIFIED',
42
- 'AGT' => 'LA_DATE_MODIFIED',
43
- 'OFF' => 'LO_DATE_MODIFIED'
44
- }
45
-
11
+
46
12
  def self.config
47
13
  return @@config
48
14
  end
@@ -52,8 +18,6 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
52
18
  'url' => nil, # URL to the RETS login
53
19
  'username' => nil,
54
20
  'password' => nil,
55
- 'limit' => nil, # How many records to limit per request
56
- 'days_per_batch' => nil, # When performing a large property import, how many days to search on per batch
57
21
  'temp_path' => nil,
58
22
  'log_file' => nil,
59
23
  'media_base_url' => nil
@@ -77,37 +41,83 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
77
41
  end
78
42
 
79
43
  #=============================================================================
80
- # Main updater
44
+ # Import method
81
45
  #=============================================================================
82
46
 
83
- def self.update_after(date_modified)
84
- self.update_data_after(date_modified)
85
- self.update_images_after(date_modified)
86
- end
87
-
88
- def self.update_data_after(date_modified)
89
- self.get_config if @@config.nil? || @@config['url'].nil?
90
- self.import_modified_after(date_modified, 'Agent' , 'AGT')
91
- self.import_modified_after(date_modified, 'Office' , 'OFF')
92
- self.import_modified_after(date_modified, 'OpenHouse' , 'OPH')
93
- #self.import_modified_after(date_modified, 'Property' , 'COM')
94
- self.import_modified_after(date_modified, 'Property' , 'LND')
95
- self.import_modified_after(date_modified, 'Property' , 'MUL')
96
- self.import_modified_after(date_modified, 'Property' , 'RES')
47
+ def self.import(query, search_type, class_type)
48
+ self.log("Importing #{search_type}:#{class_type} with query #{query}...")
49
+ self.get_config if @@config.nil? || @@config['url'].nil?
50
+ params = {
51
+ :search_type => search_type,
52
+ :class => class_type,
53
+ :query => query,
54
+ :limit => -1,
55
+ :timeout => -1
56
+ }
57
+ obj = nil
58
+ self.client.search(params) do |data|
59
+ obj = self.get_instance_with_id(class_type, data)
60
+ if obj.nil?
61
+ self.log("Error: object is nil")
62
+ self.log(data.inspect)
63
+ next
64
+ end
65
+ obj.parse(data)
66
+ obj.save
67
+ end
97
68
  end
98
69
 
99
- def self.update_images_after(date_modified)
100
- self.get_config if @@config.nil? || @@config['url'].nil?
101
- self.download_agent_images_modified_after(date_modified)
102
- self.download_property_images_modified_after(date_modified)
70
+ def self.get_instance_with_id(class_type, data)
71
+ obj = nil
72
+ m = case class_type
73
+ when 'OPH' then CabooseRets::OpenHouse
74
+ when 'GFX' then CabooseRets::Media
75
+ when 'COM' then CabooseRets::CommercialProperty
76
+ when 'LND' then CabooseRets::LandProperty
77
+ when 'MUL' then CabooseRets::MultiFamilyProperty
78
+ when 'RES' then CabooseRets::ResidentialProperty
79
+ when 'AGT' then CabooseRets::Agent
80
+ when 'OFF' then CabooseRets::Office
81
+ end
82
+ obj = case class_type
83
+ 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 )
84
+ 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'] )
85
+ 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 )
86
+ 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 )
87
+ 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 )
88
+ 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 )
89
+ 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'] )
90
+ 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'] )
91
+ end
92
+ return obj
103
93
  end
104
94
 
105
95
  #=============================================================================
106
- # Data
96
+ # Main updater
107
97
  #=============================================================================
108
-
109
- def self.import_property(mls_acct)
98
+
99
+ def self.update_after(date_modified)
100
+ self.update_residential_properties_modified_after(date_modified)
101
+ self.update_commercial_properties_modified_after(date_modified)
102
+ self.update_land_properties_modified_after(date_modified)
103
+ self.update_multi_family_properties_modified_after(date_modified)
104
+ self.update_offices_modified_after(date_modified)
105
+ self.update_agents_modified_after(date_modified)
106
+ self.update_open_houses_modified_after(date_modified)
107
+ end
108
+ def self.update_residential_properties_modified_after(date_modified) self.client.search({ :search_type => 'Property' , :class => 'RES', :select => ['MLS_ACCT'] , :query => "(DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)" , :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_residential_property data['MLS_ACCT' ] } end
109
+ def self.update_commercial_properties_modified_after(date_modified) self.client.search({ :search_type => 'Property' , :class => 'COM', :select => ['MLS_ACCT'] , :query => "(DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)" , :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_commercial_property data['MLS_ACCT' ] } end
110
+ def self.update_land_properties_modified_after(date_modified) self.client.search({ :search_type => 'Property' , :class => 'LND', :select => ['MLS_ACCT'] , :query => "(DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)" , :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_land_property data['MLS_ACCT' ] } end
111
+ def self.update_multi_family_properties_modified_after(date_modified) self.client.search({ :search_type => 'Property' , :class => 'MUL', :select => ['MLS_ACCT'] , :query => "(DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)" , :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_multi_family_property data['MLS_ACCT' ] } end
112
+ def self.update_offices_modified_after(date_modified) self.client.search({ :search_type => 'Office' , :class => 'OFF', :select => ['LO_LO_CODE'] , :query => "(LO_DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)", :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_office data['LO_LO_CODE'] } end
113
+ def self.update_agents_modified_after(date_modified) self.client.search({ :search_type => 'Agent' , :class => 'AGT', :select => ['LA_LA_CODE'] , :query => "(LA_DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)", :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_agent data['LA_LA_CODE'] } end
114
+ def self.update_open_houses_modified_after(date_modified) self.client.search({ :search_type => 'OpenHouse', :class => 'OPH', :select => ['ID'] , :query => "(DATE_MODIFIED=#{date_modified.strftime("%FT%T")}+)" , :standard_names_only => true, :timeout => -1 }) { |data| self.delay.import_open_house data['ID' ] } end
110
115
 
116
+ #=============================================================================
117
+ # Single model import methods (called from a worker dyno)
118
+ #=============================================================================
119
+
120
+ def self.import_property(mls_acct)
111
121
  self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'RES')
112
122
  p = CabooseRets::ResidentialProperty.where(:id => mls_acct.to_i).first
113
123
  if p.nil?
@@ -126,143 +136,53 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
126
136
  self.download_property_images(p)
127
137
  end
128
138
 
129
- def self.import_modified_after(date_modified, search_type = nil, class_type = nil)
130
- self.get_config if @@config.nil? || @@config['url'].nil?
131
-
132
- d = date_modified
133
- date_modified_field = @@date_modified_fields[class_type]
134
-
135
- while d.strftime('%FT%T') <= DateTime.now.strftime('%FT%T') do
136
- break if d.nil?
137
-
138
- d2 = d.strftime('%FT%T')
139
- d2 << "-"
140
- d2 << (d+@@config['days_per_batch']).strftime('%FT%T')
141
-
142
- query = "(#{date_modified_field}=#{d2})"
143
- self.import(query, search_type, class_type)
144
-
145
- d = d + @@config['days_per_batch']
146
- end
139
+ def self.import_residential_property(mls_acct)
140
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'RES')
141
+ p = CabooseRets::ResidentialProperty.where(:id => mls_acct.to_i).first
142
+ self.download_property_images(p)
143
+ self.update_coords(p)
147
144
  end
148
145
 
149
- def self.import(query, search_type, class_type)
150
- # See how many records we have
151
- self.client.search(
152
- :search_type => search_type,
153
- :class => class_type,
154
- :query => query,
155
- :count_mode => :only,
156
- :timeout => -1,
157
- )
158
- # Return if no records found
159
- if (self.client.rets_data[:code] == "20201")
160
- self.log "No #{search_type}:#{class_type} records found for query: #{query}"
161
- return
162
- else
163
- count = self.client.rets_data[:count]
164
- self.log "Importing #{count} #{search_type}:#{class_type} record" + (count == 1 ? "" : "s") + "..."
165
- end
166
-
167
- count = self.client.rets_data[:count]
168
- batch_count = (count.to_f/@@config['limit'].to_f).ceil
169
-
170
- (0...batch_count).each do |i|
171
- params = {
172
- :search_type => search_type,
173
- :class => class_type,
174
- :query => query,
175
- :limit => @@config['limit'],
176
- :offset => @@config['limit'] * i,
177
- :timeout => -1
178
- }
179
- obj = nil
180
- self.client.search(params) do |data|
181
- m = @@models[class_type]
182
- #key_field = @@key_fields[search_type]
183
- #id = data[key_field].to_i
184
- #obj = m.exists?(id) ? m.find(id) : m.new
185
- obj = self.get_instance_with_id(m, data)
186
- if obj.nil?
187
- puts "Error: object is nil"
188
- puts m.inspect
189
- puts data.inspect
190
- next
191
- end
192
- obj.parse(data)
193
- #obj.id = id
194
- obj.save
195
- end
196
-
197
- case obj
198
- when CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty
199
- self.update_coords(obj)
200
- end
201
- end
146
+ def self.import_commercial_property(mls_acct)
147
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'COM')
148
+ p = CabooseRets::CommercialProperty.where(:id => mls_acct.to_i).first
149
+ self.download_property_images(p)
150
+ self.update_coords(p)
202
151
  end
203
152
 
204
- def self.get_instance_with_id(model, data)
205
- obj = nil
206
- m = model.constantize
207
- case model
208
- when 'CabooseRets::OpenHouse' then obj = m.where(:id => data['ID'].to_i ).exists? ? m.where(:id => data['ID'].to_i ).first : m.new(:id => data['ID'].to_i )
209
- when 'CabooseRets::Media' then obj = m.where(:media_id => data['MEDIA_ID'] ).exists? ? m.where(:media_id => data['MEDIA_ID'] ).first : m.new(:media_id => data['MEDIA_ID'] )
210
- when 'CabooseRets::CommercialProperty' then obj = 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 )
211
- when 'CabooseRets::LandProperty' then obj = 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 )
212
- when 'CabooseRets::MultiFamilyProperty' then obj = 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 )
213
- when 'CabooseRets::ResidentialProperty' then obj = 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 )
214
- when 'CabooseRets::Agent' then obj = 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'] )
215
- when 'CabooseRets::Office' then obj = 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'] )
216
- end
217
- return obj
153
+ def self.import_land_property(mls_acct)
154
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'LND')
155
+ p = CabooseRets::LandProperty.where(:id => mls_acct.to_i).first
156
+ self.download_property_images(p)
157
+ self.update_coords(p)
218
158
  end
219
159
 
220
- #=============================================================================
221
- # Agent Images
222
- #=============================================================================
160
+ def self.import_multi_family_property(mls_acct)
161
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'MUL')
162
+ p = CabooseRets::MultiFamilyProperty.where(:id => mls_acct.to_i).first
163
+ self.download_property_images(p)
164
+ self.update_coords(p)
165
+ end
223
166
 
224
- def self.download_agent_images_modified_after(date_modified, agent = nil)
225
- if agent.nil?
226
- CabooseRets::Agent.where('photo_date_modified > ?', date_modified.strftime('%FT%T')).reorder('last_name, first_name').all.each do |a|
227
- self.download_agent_images_modified_after(date_modified, a)
228
- end
229
- return
230
- end
231
- self.download_agent_images(agent)
167
+ def self.import_office(lo_code)
168
+ self.import("(LO_LO_CODE=*#{lo_code}*)", 'Office', 'OFF')
169
+ office = CabooseRets::Office.where(:lo_code => lo_code.to_s).first
170
+ self.download_office_image(office)
232
171
  end
233
172
 
234
- def self.download_agent_images(agent)
235
- a = agent
236
- self.log "Saving image for #{a.first_name} #{a.last_name}..."
237
- begin
238
- self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => a.la_code) do |headers, content|
239
- a.image = URI.parse(headers['location'])
240
- a.save
241
- end
242
- rescue RETS::APIError => err
243
- self.log "No image for #{a.first_name} #{a.last_name}."
244
- end
173
+ def self.import_agent(la_code)
174
+ self.import("(LA_LA_CODE=*#{la_code}*)", 'Agent', 'AGT')
175
+ a = CabooseRets::Agent.where(:la_code => la_code.to_s).first
176
+ self.download_agent_image(a)
245
177
  end
246
178
 
179
+ def self.import_open_house(id)
180
+ self.import("(ID=*#{id}*)", 'OpenHouse', 'OPH')
181
+ end
182
+
247
183
  #=============================================================================
248
- # Property Images
184
+ # Images
249
185
  #=============================================================================
250
-
251
- def self.download_property_images_modified_after(date_modified)
252
- models = [CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty]
253
- names = ["commercial", "land", "multi-family", "residential"]
254
- i = 0
255
- models.each do |model|
256
- count = model.where("photo_date_modified > ?", date_modified.strftime('%FT%T')).count
257
- j = 1
258
- model.where("photo_date_modified > ?", date_modified.strftime('%FT%T')).reorder(:mls_acct).each do |p|
259
- self.log("Downloading images for #{j} of #{count} #{names[i]} properties...")
260
- self.download_property_images(p)
261
- j = j + 1
262
- end
263
- i = i + 1
264
- end
265
- end
266
186
 
267
187
  def self.download_property_images(p)
268
188
  self.refresh_property_media(p)
@@ -311,115 +231,29 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
311
231
  end
312
232
  end
313
233
 
314
- def self.refresh_all_virtual_tours
315
- # See how many records we have
316
- self.client.search(
317
- :search_type => 'Media',
318
- :class => 'GFX',
319
- :query => "(MEDIA_TYPE=|V)",
320
- :count_mode => :only,
321
- :timeout => -1
322
- )
323
- # Return if no records found
324
- if (self.client.rets_data[:code] == "20201")
325
- self.log "No virtual tours found."
326
- return
327
- else
328
- count = self.client.rets_data[:count]
329
- self.log "Importing #{count} virtual tours..."
330
- end
331
-
332
- count = self.client.rets_data[:count]
333
- batch_count = (count.to_f/@@config['limit'].to_f).ceil
334
-
335
- (0...batch_count).each do |i|
336
- params = {
337
- :search_type => 'Media',
338
- :class => 'GFX',
339
- :query => "(MEDIA_TYPE=|V)",
340
- :limit => @@config['limit'],
341
- :offset => @@config['limit'] * i,
342
- :timeout => -1
343
- }
344
- obj = nil
345
- self.client.search(params) do |data|
346
- mls_acct = data['MLS_ACCT'].to_i
347
- m = CabooseRets::Media.exists?("mls_acct = '#{mls_acct}' and media_type = 'Virtual Tour'") ? CabooseRets::Media.where("mls_acct = '#{mls_acct}' and media_type = 'Virtual Tour'").first : CabooseRets::Media.new
348
- m.parse(data)
349
- m.save
350
- end
351
- end
234
+ def self.download_agent_image(agent)
235
+ self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
236
+ begin
237
+ self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => agent.la_code) do |headers, content|
238
+ agent.image = URI.parse(headers['location'])
239
+ agent.save
240
+ end
241
+ rescue RETS::APIError => err
242
+ self.log "No image for #{agent.first_name} #{agent.last_name}."
243
+ end
352
244
  end
353
245
 
354
- def self.refresh_virtual_tours(p)
355
- self.log("-- Deleting images and metadata for #{p.mls_acct}...")
356
- CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
357
-
358
- self.log("-- Downloading image metadata for #{p.mls_acct}...")
359
- params = {
360
- :search_type => 'Media',
361
- :class => 'GFX',
362
- #:query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
363
- :query => "(MLS_ACCT=*#{p.id}*)",
364
- :timeout => -1
365
- }
366
- self.client.search(params) do |data|
367
- m = CabooseRets::Media.new
368
- m.parse(data)
369
- #m.id = m.media_id
370
- m.save
371
- end
246
+ def self.download_office_image(office)
247
+ self.log "Saving image for #{office.lo_name}..."
248
+ begin
249
+ self.client.get_object(:resource => :Office, :type => :Photo, :location => true, :id => office.lo_code) do |headers, content|
250
+ office.image = URI.parse(headers['location'])
251
+ office.save
252
+ end
253
+ rescue RETS::APIError => err
254
+ self.log "No image for #{office.lo_name}."
255
+ end
372
256
  end
373
-
374
- #def self.download_property_images(p)
375
- #
376
- # self.log("-- Deleting images and metadata for #{p.mls_acct}...")
377
- # CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
378
- #
379
- # self.log("-- Downloading image metadata for #{p.mls_acct}...")
380
- # params = {
381
- # :search_type => 'Media',
382
- # :class => 'GFX',
383
- # :query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
384
- # :timeout => -1
385
- # }
386
- # puts "Before search #{p.id}"
387
- # self.client.search(params) do |data|
388
- # puts "download_property_images self.client.search #{p.id}"
389
- # #m = CabooseRets::Media.new
390
- # #m.parse(data)
391
- # #m.id = m.media_id
392
- # #m.save
393
- # self.download_property_images2(p)
394
- # end
395
- # puts "After search #{p.id}"
396
- #end
397
- #
398
- #def self.download_property_images2(p)
399
- # puts "download_property_images2 #{p.id}"
400
- # sleep(1)
401
- #
402
- # #self.log("-- Downloading images and resizing for #{p.mls_acct}")
403
- # #media = []
404
- # #self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
405
- # #
406
- # ## Find the associated media record for the image
407
- # #filename = File.basename(headers['location'])
408
- # #m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
409
- # #
410
- # #if m.nil?
411
- # # self.log("Can't find media record for #{p.mls_acct} #{filename}.")
412
- # #else
413
- # # m.image = URI.parse(headers['location'])
414
- # # media << m
415
- # # #m.save
416
- # #end
417
- # #
418
- # #self.log("-- Uploading images to S3 for #{p.mls_acct}")
419
- # #media.each do |m|
420
- # # m.save
421
- # #end
422
- #end
423
257
 
424
258
  #=============================================================================
425
259
  # GPS
@@ -0,0 +1,512 @@
1
+ require 'ruby-rets'
2
+ require 'httparty'
3
+ require 'json'
4
+
5
+ # http://rets.solidearth.com/ClientHome.aspx
6
+
7
+ class CabooseRets::RetsImporter # < ActiveRecord::Base
8
+
9
+ @@rets_client = nil
10
+ @@config = nil
11
+ @@object_types = {
12
+ 'OpenHouse' => ['OPH'],
13
+ 'Media' => ['GFX'],
14
+ 'Property' => ['COM', 'LND', 'MUL', 'RES'],
15
+ 'Agent' => ['AGT'],
16
+ 'Office' => ['OFF']
17
+ }
18
+ @@key_fields = {
19
+ 'OpenHouse' => 'ID',
20
+ 'Media' => 'MEDIA_ID',
21
+ 'Property' => 'MLS_ACCT',
22
+ 'Agent' => 'LA_LA_CODE',
23
+ 'Office' => 'LO_LO_CODE'
24
+ }
25
+ @@models = {
26
+ 'OPH' => 'CabooseRets::OpenHouse',
27
+ 'GFX' => 'CabooseRets::Media',
28
+ 'COM' => 'CabooseRets::CommercialProperty',
29
+ 'LND' => 'CabooseRets::LandProperty',
30
+ 'MUL' => 'CabooseRets::MultiFamilyProperty',
31
+ 'RES' => 'CabooseRets::ResidentialProperty',
32
+ 'AGT' => 'CabooseRets::Agent',
33
+ 'OFF' => 'CabooseRets::Office'
34
+ }
35
+ @@date_modified_fields = {
36
+ 'OPH' => 'DATE_MODIFIED',
37
+ 'GFX' => 'DATE_MODIFIED',
38
+ 'COM' => 'DATE_MODIFIED',
39
+ 'LND' => 'DATE_MODIFIED',
40
+ 'MUL' => 'DATE_MODIFIED',
41
+ 'RES' => 'DATE_MODIFIED',
42
+ 'AGT' => 'LA_DATE_MODIFIED',
43
+ 'OFF' => 'LO_DATE_MODIFIED'
44
+ }
45
+
46
+ def self.config
47
+ return @@config
48
+ end
49
+
50
+ def self.get_config
51
+ @@config = {
52
+ 'url' => nil, # URL to the RETS login
53
+ 'username' => nil,
54
+ 'password' => nil,
55
+ 'limit' => nil, # How many records to limit per request
56
+ 'days_per_batch' => nil, # When performing a large property import, how many days to search on per batch
57
+ 'temp_path' => nil,
58
+ 'log_file' => nil,
59
+ 'media_base_url' => nil
60
+ }
61
+ config = YAML::load(File.open("#{Rails.root}/config/rets_importer.yml"))
62
+ config = config[Rails.env]
63
+ config.each { |key,val| @@config[key] = val }
64
+ end
65
+
66
+ def self.client
67
+ self.get_config if @@config.nil? || @@config['url'].nil?
68
+
69
+ if (@@rets_client.nil?)
70
+ @@rets_client = RETS::Client.login(
71
+ :url => @@config['url'],
72
+ :username => @@config['username'],
73
+ :password => @@config['password']
74
+ )
75
+ end
76
+ return @@rets_client
77
+ end
78
+
79
+ #=============================================================================
80
+ # Main updater
81
+ #=============================================================================
82
+
83
+ def self.update_after(date_modified)
84
+ self.update_data_after(date_modified)
85
+ self.update_images_after(date_modified)
86
+ end
87
+
88
+ def self.update_data_after(date_modified)
89
+ self.get_config if @@config.nil? || @@config['url'].nil?
90
+ self.import_modified_after(date_modified, 'Agent' , 'AGT')
91
+ self.import_modified_after(date_modified, 'Office' , 'OFF')
92
+ self.import_modified_after(date_modified, 'OpenHouse' , 'OPH')
93
+ #self.import_modified_after(date_modified, 'Property' , 'COM')
94
+ self.import_modified_after(date_modified, 'Property' , 'LND')
95
+ self.import_modified_after(date_modified, 'Property' , 'MUL')
96
+ self.import_modified_after(date_modified, 'Property' , 'RES')
97
+ end
98
+
99
+ def self.update_images_after(date_modified)
100
+ self.get_config if @@config.nil? || @@config['url'].nil?
101
+ self.download_agent_images_modified_after(date_modified)
102
+ self.download_property_images_modified_after(date_modified)
103
+ end
104
+
105
+ #=============================================================================
106
+ # Data
107
+ #=============================================================================
108
+
109
+ def self.import_property(mls_acct)
110
+
111
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'RES')
112
+ p = CabooseRets::ResidentialProperty.where(:id => mls_acct.to_i).first
113
+ if p.nil?
114
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'COM')
115
+ p = CabooseRets::CommercialProperty.where(:id => mls_acct.to_i).first
116
+ if p.nil?
117
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'LND')
118
+ p = CabooseRets::LandProperty.where(:id => mls_acct.to_i).first
119
+ if p.nil?
120
+ self.import("(MLS_ACCT=*#{mls_acct}*)", 'Property', 'MUL')
121
+ p = CabooseRets::MultiFamilyProperty.where(:id => mls_acct.to_i).first
122
+ return if p.nil?
123
+ end
124
+ end
125
+ end
126
+ self.download_property_images(p)
127
+ end
128
+
129
+ def self.import_modified_after(date_modified, search_type = nil, class_type = nil)
130
+ self.get_config if @@config.nil? || @@config['url'].nil?
131
+
132
+ d = date_modified
133
+ date_modified_field = @@date_modified_fields[class_type]
134
+
135
+ while d.strftime('%FT%T') <= DateTime.now.strftime('%FT%T') do
136
+ break if d.nil?
137
+
138
+ d2 = d.strftime('%FT%T')
139
+ d2 << "-"
140
+ d2 << (d+@@config['days_per_batch']).strftime('%FT%T')
141
+
142
+ query = "(#{date_modified_field}=#{d2})"
143
+ self.import(query, search_type, class_type)
144
+
145
+ d = d + @@config['days_per_batch']
146
+ end
147
+ end
148
+
149
+ def self.import(query, search_type, class_type)
150
+ # See how many records we have
151
+ self.client.search(
152
+ :search_type => search_type,
153
+ :class => class_type,
154
+ :query => query,
155
+ :count_mode => :only,
156
+ :timeout => -1,
157
+ )
158
+ # Return if no records found
159
+ if (self.client.rets_data[:code] == "20201")
160
+ self.log "No #{search_type}:#{class_type} records found for query: #{query}"
161
+ return
162
+ else
163
+ count = self.client.rets_data[:count]
164
+ self.log "Importing #{count} #{search_type}:#{class_type} record" + (count == 1 ? "" : "s") + "..."
165
+ end
166
+
167
+ count = self.client.rets_data[:count]
168
+ batch_count = (count.to_f/@@config['limit'].to_f).ceil
169
+
170
+ (0...batch_count).each do |i|
171
+ params = {
172
+ :search_type => search_type,
173
+ :class => class_type,
174
+ :query => query,
175
+ :limit => @@config['limit'],
176
+ :offset => @@config['limit'] * i,
177
+ :timeout => -1
178
+ }
179
+ obj = nil
180
+ self.client.search(params) do |data|
181
+ m = @@models[class_type]
182
+ #key_field = @@key_fields[search_type]
183
+ #id = data[key_field].to_i
184
+ #obj = m.exists?(id) ? m.find(id) : m.new
185
+ obj = self.get_instance_with_id(m, data)
186
+ if obj.nil?
187
+ puts "Error: object is nil"
188
+ puts m.inspect
189
+ puts data.inspect
190
+ next
191
+ end
192
+ obj.parse(data)
193
+ #obj.id = id
194
+ obj.save
195
+ end
196
+
197
+ case obj
198
+ when CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty
199
+ self.update_coords(obj)
200
+ end
201
+ end
202
+ end
203
+
204
+ def self.get_instance_with_id(model, data)
205
+ obj = nil
206
+ m = model.constantize
207
+ case model
208
+ when 'CabooseRets::OpenHouse' then obj = m.where(:id => data['ID'].to_i ).exists? ? m.where(:id => data['ID'].to_i ).first : m.new(:id => data['ID'].to_i )
209
+ when 'CabooseRets::Media' then obj = m.where(:media_id => data['MEDIA_ID'] ).exists? ? m.where(:media_id => data['MEDIA_ID'] ).first : m.new(:media_id => data['MEDIA_ID'] )
210
+ when 'CabooseRets::CommercialProperty' then obj = 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 )
211
+ when 'CabooseRets::LandProperty' then obj = 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 )
212
+ when 'CabooseRets::MultiFamilyProperty' then obj = 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 )
213
+ when 'CabooseRets::ResidentialProperty' then obj = 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 )
214
+ when 'CabooseRets::Agent' then obj = 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'] )
215
+ when 'CabooseRets::Office' then obj = 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'] )
216
+ end
217
+ return obj
218
+ end
219
+
220
+ #=============================================================================
221
+ # Agent Images
222
+ #=============================================================================
223
+
224
+ def self.download_agent_images_modified_after(date_modified, agent = nil)
225
+ if agent.nil?
226
+ CabooseRets::Agent.where('photo_date_modified > ?', date_modified.strftime('%FT%T')).reorder('last_name, first_name').all.each do |a|
227
+ self.download_agent_images_modified_after(date_modified, a)
228
+ end
229
+ return
230
+ end
231
+ self.download_agent_images(agent)
232
+ end
233
+
234
+ def self.download_agent_images(agent)
235
+ a = agent
236
+ self.log "Saving image for #{a.first_name} #{a.last_name}..."
237
+ begin
238
+ self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => a.la_code) do |headers, content|
239
+ a.image = URI.parse(headers['location'])
240
+ a.save
241
+ end
242
+ rescue RETS::APIError => err
243
+ self.log "No image for #{a.first_name} #{a.last_name}."
244
+ end
245
+ end
246
+
247
+ #=============================================================================
248
+ # Property Images
249
+ #=============================================================================
250
+
251
+ def self.download_property_images_modified_after(date_modified)
252
+ models = [CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty]
253
+ names = ["commercial", "land", "multi-family", "residential"]
254
+ i = 0
255
+ models.each do |model|
256
+ count = model.where("photo_date_modified > ?", date_modified.strftime('%FT%T')).count
257
+ j = 1
258
+ model.where("photo_date_modified > ?", date_modified.strftime('%FT%T')).reorder(:mls_acct).each do |p|
259
+ self.log("Downloading images for #{j} of #{count} #{names[i]} properties...")
260
+ self.download_property_images(p)
261
+ j = j + 1
262
+ end
263
+ i = i + 1
264
+ end
265
+ end
266
+
267
+ def self.download_property_images(p)
268
+ self.refresh_property_media(p)
269
+
270
+ self.log("-- Downloading images and resizing for #{p.mls_acct}")
271
+ media = []
272
+ self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
273
+
274
+ # Find the associated media record for the image
275
+ filename = File.basename(headers['location'])
276
+ m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
277
+
278
+ if m.nil?
279
+ self.log("Can't find media record for #{p.mls_acct} #{filename}.")
280
+ else
281
+ m.image = URI.parse(headers['location'])
282
+ media << m
283
+ #m.save
284
+ end
285
+ end
286
+
287
+ self.log("-- Uploading images to S3 for #{p.mls_acct}")
288
+ media.each do |m|
289
+ m.save
290
+ end
291
+ end
292
+
293
+ def self.refresh_property_media(p)
294
+ self.log("-- Deleting images and metadata for #{p.mls_acct}...")
295
+ #CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
296
+ CabooseRets::Media.where(:mls_acct => p.mls_acct).destroy_all
297
+
298
+ self.log("-- Downloading image metadata for #{p.mls_acct}...")
299
+ params = {
300
+ :search_type => 'Media',
301
+ :class => 'GFX',
302
+ #:query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
303
+ :query => "(MLS_ACCT=*#{p.id}*)",
304
+ :timeout => -1
305
+ }
306
+ self.client.search(params) do |data|
307
+ m = CabooseRets::Media.new
308
+ m.parse(data)
309
+ #m.id = m.media_id
310
+ m.save
311
+ end
312
+ end
313
+
314
+ def self.refresh_all_virtual_tours
315
+ # See how many records we have
316
+ self.client.search(
317
+ :search_type => 'Media',
318
+ :class => 'GFX',
319
+ :query => "(MEDIA_TYPE=|V)",
320
+ :count_mode => :only,
321
+ :timeout => -1
322
+ )
323
+ # Return if no records found
324
+ if (self.client.rets_data[:code] == "20201")
325
+ self.log "No virtual tours found."
326
+ return
327
+ else
328
+ count = self.client.rets_data[:count]
329
+ self.log "Importing #{count} virtual tours..."
330
+ end
331
+
332
+ count = self.client.rets_data[:count]
333
+ batch_count = (count.to_f/@@config['limit'].to_f).ceil
334
+
335
+ (0...batch_count).each do |i|
336
+ params = {
337
+ :search_type => 'Media',
338
+ :class => 'GFX',
339
+ :query => "(MEDIA_TYPE=|V)",
340
+ :limit => @@config['limit'],
341
+ :offset => @@config['limit'] * i,
342
+ :timeout => -1
343
+ }
344
+ obj = nil
345
+ self.client.search(params) do |data|
346
+ mls_acct = data['MLS_ACCT'].to_i
347
+ m = CabooseRets::Media.exists?("mls_acct = '#{mls_acct}' and media_type = 'Virtual Tour'") ? CabooseRets::Media.where("mls_acct = '#{mls_acct}' and media_type = 'Virtual Tour'").first : CabooseRets::Media.new
348
+ m.parse(data)
349
+ m.save
350
+ end
351
+ end
352
+ end
353
+
354
+ def self.refresh_virtual_tours(p)
355
+ self.log("-- Deleting images and metadata for #{p.mls_acct}...")
356
+ CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
357
+
358
+ self.log("-- Downloading image metadata for #{p.mls_acct}...")
359
+ params = {
360
+ :search_type => 'Media',
361
+ :class => 'GFX',
362
+ #:query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
363
+ :query => "(MLS_ACCT=*#{p.id}*)",
364
+ :timeout => -1
365
+ }
366
+ self.client.search(params) do |data|
367
+ m = CabooseRets::Media.new
368
+ m.parse(data)
369
+ #m.id = m.media_id
370
+ m.save
371
+ end
372
+ end
373
+
374
+ #def self.download_property_images(p)
375
+ #
376
+ # self.log("-- Deleting images and metadata for #{p.mls_acct}...")
377
+ # CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
378
+ #
379
+ # self.log("-- Downloading image metadata for #{p.mls_acct}...")
380
+ # params = {
381
+ # :search_type => 'Media',
382
+ # :class => 'GFX',
383
+ # :query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
384
+ # :timeout => -1
385
+ # }
386
+ # puts "Before search #{p.id}"
387
+ # self.client.search(params) do |data|
388
+ # puts "download_property_images self.client.search #{p.id}"
389
+ # #m = CabooseRets::Media.new
390
+ # #m.parse(data)
391
+ # #m.id = m.media_id
392
+ # #m.save
393
+ # self.download_property_images2(p)
394
+ # end
395
+ # puts "After search #{p.id}"
396
+ #end
397
+ #
398
+ #def self.download_property_images2(p)
399
+ # puts "download_property_images2 #{p.id}"
400
+ # sleep(1)
401
+ #
402
+ # #self.log("-- Downloading images and resizing for #{p.mls_acct}")
403
+ # #media = []
404
+ # #self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
405
+ # #
406
+ # ## Find the associated media record for the image
407
+ # #filename = File.basename(headers['location'])
408
+ # #m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
409
+ # #
410
+ # #if m.nil?
411
+ # # self.log("Can't find media record for #{p.mls_acct} #{filename}.")
412
+ # #else
413
+ # # m.image = URI.parse(headers['location'])
414
+ # # media << m
415
+ # # #m.save
416
+ # #end
417
+ # #
418
+ # #self.log("-- Uploading images to S3 for #{p.mls_acct}")
419
+ # #media.each do |m|
420
+ # # m.save
421
+ # #end
422
+ #end
423
+
424
+ #=============================================================================
425
+ # GPS
426
+ #=============================================================================
427
+
428
+ def self.update_coords(p = nil)
429
+ if p.nil?
430
+ models = [CabooseRets::CommercialProperty, CabooseRets::LandProperty, CabooseRets::MultiFamilyProperty, CabooseRets::ResidentialProperty]
431
+ names = ["commercial", "land", "multi-family", "residential"]
432
+ i = 0
433
+ models.each do |model|
434
+ self.log "Updating coords #{names[i]} properties..."
435
+ model.where(:latitude => nil).reorder(:mls_acct).each do |p|
436
+ self.update_coords(p)
437
+ end
438
+ i = i + 1
439
+ end
440
+ return
441
+ end
442
+
443
+ self.log "Getting coords for mls_acct #{p.mls_acct}..."
444
+ coords = self.coords_from_address(CGI::escape "#{p.street_num} #{p.street_name}, #{p.city}, #{p.state} #{p.zip}")
445
+ return if coords.nil? || coords == false
446
+
447
+ p.latitude = coords['lat']
448
+ p.longitude = coords['lng']
449
+ p.save
450
+ end
451
+
452
+ def self.coords_from_address(address)
453
+ begin
454
+ uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
455
+ uri.gsub!(" ", "+")
456
+ resp = HTTParty.get(uri)
457
+ json = JSON.parse(resp.body)
458
+ return json['results'][0]['geometry']['location']
459
+ rescue
460
+ self.log "Error: #{uri}"
461
+ sleep(2)
462
+ return false
463
+ end
464
+ end
465
+
466
+ #=============================================================================
467
+ # Logging
468
+ #=============================================================================
469
+
470
+ def self.log(msg)
471
+ #puts "[rets_importer] #{msg}"
472
+ Rails.logger.info("[rets_importer] #{msg}")
473
+ end
474
+
475
+ #=============================================================================
476
+ # Locking update task
477
+ #=============================================================================
478
+
479
+ def self.last_updated
480
+ if !Caboose::Setting.exists?(:name => 'rets_last_updated')
481
+ Caboose::Setting.create(:name => 'rets_last_updated', :value => '2013-08-06T00:00:01')
482
+ end
483
+ s = Caboose::Setting.where(:name => 'rets_last_updated').first
484
+ return DateTime.parse(s.value)
485
+ end
486
+
487
+ def self.save_last_updated(d)
488
+ s = Caboose::Setting.where(:name => 'rets_last_updated').first
489
+ s.value = d.strftime('%FT%T')
490
+ s.save
491
+ end
492
+
493
+ def self.task_is_locked
494
+ return Caboose::Setting.exists?(:name => 'rets_update_running')
495
+ end
496
+
497
+ def self.lock_task
498
+ d = DateTime.now.utc - 5.hours
499
+ Caboose::Setting.create(:name => 'rets_update_running', :value => d.strftime('%F %T'))
500
+ return d
501
+ end
502
+
503
+ def self.unlock_task
504
+ Caboose::Setting.where(:name => 'rets_update_running').first.destroy
505
+ end
506
+
507
+ def self.unlock_task_if_last_updated(d)
508
+ setting = Caboose::Setting.where(:name => 'rets_update_running').first
509
+ self.unlock_task if setting && d.strftime('%F %T') == setting.value
510
+ end
511
+
512
+ end
@@ -1,3 +1,3 @@
1
1
  module CabooseRets
2
- VERSION = '0.0.52'
2
+ VERSION = '0.0.53'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caboose-rets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.52
4
+ version: 0.0.53
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Barry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-11 00:00:00.000000000 Z
11
+ date: 2014-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: caboose-cms
@@ -55,6 +55,7 @@ files:
55
55
  - app/models/caboose_rets/open_house.rb
56
56
  - app/models/caboose_rets/residential_property.rb
57
57
  - app/models/caboose_rets/rets_importer.rb
58
+ - app/models/caboose_rets/rets_importer_bak.rb
58
59
  - app/models/caboose_rets/rets_plugin.rb
59
60
  - app/models/caboose_rets/saved_property.rb
60
61
  - app/models/caboose_rets/saved_search.rb