caboose-rets 0.0.2

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.
Files changed (81) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +4 -0
  4. data/Rakefile +38 -0
  5. data/app/controllers/caboose_rets/agents_controller.rb +169 -0
  6. data/app/controllers/caboose_rets/application_controller.rb +6 -0
  7. data/app/controllers/caboose_rets/commercial_controller.rb +281 -0
  8. data/app/controllers/caboose_rets/land_controller.rb +69 -0
  9. data/app/controllers/caboose_rets/open_houses_controller.rb +60 -0
  10. data/app/controllers/caboose_rets/residential_controller.rb +108 -0
  11. data/app/helpers/caboose_rets/application_helper.rb +4 -0
  12. data/app/models/caboose_rets/agent.rb +65 -0
  13. data/app/models/caboose_rets/commercial_property.rb +214 -0
  14. data/app/models/caboose_rets/land_property.rb +143 -0
  15. data/app/models/caboose_rets/media.rb +23 -0
  16. data/app/models/caboose_rets/multi_family_property.rb +198 -0
  17. data/app/models/caboose_rets/office.rb +27 -0
  18. data/app/models/caboose_rets/open_house.rb +19 -0
  19. data/app/models/caboose_rets/residential_property.rb +236 -0
  20. data/app/models/caboose_rets/rets_importer.rb +303 -0
  21. data/app/models/caboose_rets/rets_plugin.rb +26 -0
  22. data/app/views/caboose_rets/agents/_admin_top_nav.html.erb +7 -0
  23. data/app/views/caboose_rets/agents/admin_edit.html.erb +28 -0
  24. data/app/views/caboose_rets/agents/admin_edit_bio.html.erb +31 -0
  25. data/app/views/caboose_rets/agents/admin_edit_contact_info.html.erb +31 -0
  26. data/app/views/caboose_rets/agents/admin_edit_mls_info.html.erb +71 -0
  27. data/app/views/caboose_rets/agents/admin_index.html.erb +48 -0
  28. data/app/views/caboose_rets/agents/details.html.erb +140 -0
  29. data/app/views/caboose_rets/agents/index.html.erb +163 -0
  30. data/app/views/caboose_rets/agents/listings.html.erb +121 -0
  31. data/app/views/caboose_rets/commercial/admin_edit.html.erb +452 -0
  32. data/app/views/caboose_rets/commercial/admin_index.html.erb +46 -0
  33. data/app/views/caboose_rets/commercial/details.html.erb +134 -0
  34. data/app/views/caboose_rets/commercial/index.html.erb +87 -0
  35. data/app/views/caboose_rets/open_houses/admin_new.html.erb +31 -0
  36. data/app/views/caboose_rets/residential/admin_edit.html.erb +250 -0
  37. data/app/views/caboose_rets/residential/admin_index.html.erb +44 -0
  38. data/app/views/caboose_rets/residential/details.html.erb +139 -0
  39. data/app/views/caboose_rets/residential/index.html.erb +102 -0
  40. data/app/views/caboose_rets/residential/residential_not_exists.html.erb +15 -0
  41. data/app/views/caboose_rets/residential/test_form.html.erb +4 -0
  42. data/config/routes.rb +87 -0
  43. data/lib/caboose-rets.rb +4 -0
  44. data/lib/caboose_rets/caboose_rets_helper.rb +2 -0
  45. data/lib/caboose_rets/engine.rb +7 -0
  46. data/lib/caboose_rets/version.rb +3 -0
  47. data/lib/tasks/caboose_rets.rake +855 -0
  48. data/test/caboose_test.rb +7 -0
  49. data/test/dummy/README.rdoc +261 -0
  50. data/test/dummy/Rakefile +7 -0
  51. data/test/dummy/app/assets/javascripts/application.js +15 -0
  52. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  53. data/test/dummy/app/controllers/application_controller.rb +3 -0
  54. data/test/dummy/app/helpers/application_helper.rb +2 -0
  55. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  56. data/test/dummy/config.ru +4 -0
  57. data/test/dummy/config/application.rb +59 -0
  58. data/test/dummy/config/boot.rb +10 -0
  59. data/test/dummy/config/database.yml +25 -0
  60. data/test/dummy/config/environment.rb +5 -0
  61. data/test/dummy/config/environments/development.rb +37 -0
  62. data/test/dummy/config/environments/production.rb +67 -0
  63. data/test/dummy/config/environments/test.rb +37 -0
  64. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  65. data/test/dummy/config/initializers/inflections.rb +15 -0
  66. data/test/dummy/config/initializers/mime_types.rb +5 -0
  67. data/test/dummy/config/initializers/secret_token.rb +7 -0
  68. data/test/dummy/config/initializers/session_store.rb +8 -0
  69. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  70. data/test/dummy/config/locales/en.yml +5 -0
  71. data/test/dummy/config/routes.rb +4 -0
  72. data/test/dummy/db/test.sqlite3 +0 -0
  73. data/test/dummy/log/test.log +25 -0
  74. data/test/dummy/public/404.html +26 -0
  75. data/test/dummy/public/422.html +26 -0
  76. data/test/dummy/public/500.html +25 -0
  77. data/test/dummy/public/favicon.ico +0 -0
  78. data/test/dummy/script/rails +6 -0
  79. data/test/integration/navigation_test.rb +10 -0
  80. data/test/test_helper.rb +15 -0
  81. metadata +169 -0
@@ -0,0 +1,303 @@
1
+ require 'ruby-rets'
2
+ require 'httparty'
3
+ require 'json'
4
+
5
+ # Check for examples:
6
+ # http://rets.solidearth.com/ClientHome.aspx
7
+ # https://www.flexmls.com/developers/rets/tutorials/dmql-tutorial/
8
+ # https://www.flexmls.com/developers/rets/tutorials/how-to-efficiently-replicate-rets-data/
9
+
10
+ class CabooseRets::RetsImporter # < ActiveRecord::Base
11
+
12
+ @@rets_client = nil
13
+ @@config = nil
14
+ @@object_types = {
15
+ 'OpenHouse' => ['OPH'],
16
+ 'Media' => ['GFX'],
17
+ 'Property' => ['COM', 'LND', 'MUL', 'RES'],
18
+ 'Agent' => ['AGT'],
19
+ 'Office' => ['OFF']
20
+ }
21
+ @@key_fields = {
22
+ 'OpenHouse' => 'ID',
23
+ 'Media' => 'MEDIA_ID',
24
+ 'Property' => 'MLS_ACCT',
25
+ 'Agent' => 'LA_LA_CODE',
26
+ 'Office' => 'LO_LO_CODE'
27
+ }
28
+ @@models = {
29
+ 'OPH' => 'CabooseRets::OpenHouse',
30
+ 'GFX' => 'CabooseRets::Media',
31
+ 'COM' => 'CabooseRets::CommercialProperty',
32
+ 'LND' => 'CabooseRets::LandProperty',
33
+ 'MUL' => 'CabooseRets::MultiFamilyProperty',
34
+ 'RES' => 'CabooseRets::ResidentialProperty',
35
+ 'AGT' => 'CabooseRets::Agent',
36
+ 'OFF' => 'CabooseRets::Office'
37
+ }
38
+ @@date_modified_fields = {
39
+ 'OPH' => 'DATE_MODIFIED',
40
+ 'GFX' => 'DATE_MODIFIED',
41
+ 'COM' => 'DATE_MODIFIED',
42
+ 'LND' => 'DATE_MODIFIED',
43
+ 'MUL' => 'DATE_MODIFIED',
44
+ 'RES' => 'DATE_MODIFIED',
45
+ 'AGT' => 'LA_DATE_MODIFIED',
46
+ 'OFF' => 'LO_DATE_MODIFIED'
47
+ }
48
+
49
+ def self.config
50
+ return @@config
51
+ end
52
+
53
+ def self.get_config
54
+ @@config = {
55
+ 'url' => nil, # URL to the RETS login
56
+ 'username' => nil,
57
+ 'password' => nil,
58
+ 'limit' => nil, # How many records to limit per request
59
+ 'days_per_batch' => nil, # When performing a large property import, how many days to search on per batch
60
+ 'temp_path' => nil,
61
+ 'log_file' => nil,
62
+ 'media_base_url' => nil
63
+ }
64
+ config = YAML::load(File.open("#{Rails.root}/config/rets_importer.yml"))
65
+ config = config[Rails.env]
66
+ config.each { |key,val| @@config[key] = val }
67
+ end
68
+
69
+ def self.client
70
+ self.get_config if @@config.nil? || @@config['url'].nil?
71
+
72
+ if (@@rets_client.nil?)
73
+ @@rets_client = RETS::Client.login(
74
+ :url => @@config['url'],
75
+ :username => @@config['username'],
76
+ :password => @@config['password']
77
+ )
78
+ end
79
+ return @@rets_client
80
+ end
81
+
82
+ #=============================================================================
83
+ # Main updater
84
+ #=============================================================================
85
+
86
+ def self.update_after(date_modified)
87
+ self.get_config if @@config.nil? || @@config['url'].nil?
88
+
89
+ # Import the data
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
+ #self.update_coords(obj)
98
+
99
+ # Import the images
100
+ self.download_agent_images_modified_after(date_modified)
101
+ self.download_property_images_modified_after(date_modified)
102
+ end
103
+
104
+ #=============================================================================
105
+ # Data
106
+ #=============================================================================
107
+
108
+ def self.import_modified_after(date_modified, search_type = nil, class_type = nil)
109
+ self.get_config if @@config.nil? || @@config['url'].nil?
110
+
111
+ d = date_modified
112
+ date_modified_field = @@date_modified_fields[class_type]
113
+
114
+ while d.strftime('%FT%T') <= DateTime.now.strftime('%FT%T') do
115
+ break if d.nil?
116
+
117
+ d2 = d.strftime('%FT%T')
118
+ d2 << "-"
119
+ d2 << (d+@@config['days_per_batch']).strftime('%FT%T')
120
+
121
+ query = "(#{date_modified_field}=#{d2})"
122
+ self.import(query, search_type, class_type)
123
+
124
+ d = d + @@config['days_per_batch']
125
+ end
126
+ end
127
+
128
+ def self.import(query, search_type, class_type)
129
+ # See how many records we have
130
+ self.client.search(
131
+ :search_type => search_type,
132
+ :class => class_type,
133
+ :query => query,
134
+ :count_mode => :only,
135
+ :timeout => -1,
136
+ )
137
+ # Return if no records found
138
+ if (self.client.rets_data[:code] == "20201")
139
+ self.log "No #{search_type}:#{class_type} records found for query: #{query}"
140
+ return
141
+ else
142
+ count = self.client.rets_data[:count]
143
+ self.log "Importing #{count} #{search_type}:#{class_type} record" + (count == 1 ? "" : "s") + "..."
144
+ end
145
+
146
+ count = self.client.rets_data[:count]
147
+ batch_count = (count.to_f/@@config['limit'].to_f).ceil
148
+
149
+ (0...batch_count).each do |i|
150
+ params = {
151
+ :search_type => search_type,
152
+ :class => class_type,
153
+ :query => query,
154
+ :limit => @@config['limit'],
155
+ :offset => @@config['limit'] * i,
156
+ :timeout => -1
157
+ }
158
+ obj = nil
159
+ self.client.search(params) do |data|
160
+ m = @@models[class_type].constantize
161
+ key_field = @@key_fields[search_type]
162
+ id = data[key_field].to_i
163
+ obj = m.exists?(id) ? m.find(id) : m.new
164
+ obj.parse(data)
165
+ obj.id = id
166
+ obj.save
167
+ end
168
+ end
169
+ end
170
+
171
+ #=============================================================================
172
+ # Agent Images
173
+ #=============================================================================
174
+
175
+ def self.download_agent_images_modified_after(date_modified, agent = nil)
176
+ if agent.nil?
177
+ CabooseRets::Agent.where('photo_date_modified > ?', date_modified.strftime('%FT%T')).reorder('last_name, first_name').all.each do |a|
178
+ self.download_agent_images_modified_after(date_modified, a)
179
+ end
180
+ return
181
+ end
182
+
183
+ a = agent
184
+ self.log "Saving image for #{a.first_name} #{a.last_name}..."
185
+ begin
186
+ self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => a.la_code) do |headers, content|
187
+ a.image = URI.parse(headers['location'])
188
+ a.save
189
+ end
190
+ rescue RETS::APIError => err
191
+ self.log "No image for #{a.first_name} #{a.last_name}."
192
+ end
193
+ end
194
+
195
+ #=============================================================================
196
+ # Property Images
197
+ #=============================================================================
198
+
199
+ def self.download_property_images_modified_after(date_modified)
200
+ [CommercialProperty, LandProperty, MultiFamilyProperty, ResidentialProperty].each do |model|
201
+ model.where("photo_date_modified > ?", date_modified.strftime('%FT%T')).each do |p|
202
+ self.download_property_images(p)
203
+ end
204
+ end
205
+ end
206
+
207
+ def self.download_property_images(p)
208
+ self.refresh_property_media(p)
209
+ self.client.get_object(:resource => :Property, :type => :Photo, :location => true, :id => p.id) do |headers, content|
210
+
211
+ # Find the associated media record for the image
212
+ filename = File.basename(headers['location'])
213
+ m = CabooseRets::Media.where(:mls_acct => p.mls_acct, :file_name => filename).first
214
+
215
+ if m.nil?
216
+ self.log("Can't find media record for #{p.mls_acct} #{filename}.")
217
+ else
218
+ m.image = URI.parse(headers['location'])
219
+ m.save
220
+ end
221
+
222
+ end
223
+ end
224
+
225
+ def self.refresh_property_media(p)
226
+ CabooseRets::Media.where(:mls_acct => p.mls_acct, :media_type => 'Photo').destroy_all
227
+
228
+ params = {
229
+ :search_type => 'Media',
230
+ :class => 'GFX',
231
+ :query => "(MLS_ACCT=*#{p.id}*),(MEDIA_TYPE=|I)",
232
+ :timeout => -1
233
+ }
234
+ self.client.search(params) do |data|
235
+ m = CabooseRets::Media.new
236
+ m.parse(data)
237
+ m.id = m.media_id
238
+ m.save
239
+ end
240
+ end
241
+
242
+ #=============================================================================
243
+ # GPS
244
+ #=============================================================================
245
+
246
+ def self.update_coords(p, type = 'RES')
247
+ if type == 'RES'
248
+ self.update_property_coords(ResidentialProperty, 'residential', p)
249
+ elsif type == 'COM'
250
+ self.update_property_coords(CommercialProperty, 'commercial', p)
251
+ elsif type == 'LND'
252
+ self.update_property_coords(LandProperty, 'land', p)
253
+ end
254
+ end
255
+
256
+ def self.update_property_coords(property_class, symbolic_name, property = nil)
257
+ if (property.nil?)
258
+ if (property_class.where(:latitude => nil).count == 0)
259
+ self.log "All #{symbolic_name} properties have GPS coordinates."
260
+ return
261
+ end
262
+ property_class.where(:latitude => nil).reorder(:mls_acct).each do |p|
263
+ self.update_property_coords(property_class, symbolic_name, p)
264
+ end
265
+ self.update_property_coords(property_class, symbolic_name, nil)
266
+ return
267
+ end
268
+ p = property
269
+
270
+ coords = self.coords_from_address(CGI::escape "#{p.street_num} #{p.street_name}, #{p.city}, #{p.state} #{p.zip}")
271
+ return if coords.nil? || coords == false
272
+
273
+ p.latitude = coords['lat']
274
+ p.longitude = coords['lng']
275
+ p.save
276
+ self.log "Saved #{symbolic_name} property #{p.mls_acct} coords"
277
+ end
278
+
279
+ def self.coords_from_address(address)
280
+ begin
281
+ uri = "https://maps.googleapis.com/maps/api/geocode/json?address=#{address}&sensor=false"
282
+ uri.gsub!(" ", "+")
283
+
284
+ resp = HTTParty.get(uri)
285
+ json = JSON.parse(resp.body)
286
+ return json['results'][0]['geometry']['location']
287
+ rescue
288
+ self.log "Error: #{uri}"
289
+ sleep(2)
290
+ return false
291
+ end
292
+ end
293
+
294
+ #=============================================================================
295
+ # Logging
296
+ #=============================================================================
297
+
298
+ def self.log(msg)
299
+ puts "[rets_importer] #{msg}"
300
+ Rails.logger.info("[rets_importer] #{msg}")
301
+ end
302
+
303
+ end
@@ -0,0 +1,26 @@
1
+ class AdvantagePlugin < Caboose::CaboosePlugin
2
+
3
+ def self.admin_nav(nav, user = nil, page = nil)
4
+ return nav if user.nil? || !user.is_allowed('properties', 'view')
5
+
6
+ item = {
7
+ 'id' => 'rets',
8
+ 'text' => 'RETS',
9
+ 'children' => [],
10
+ 'modal' => true
11
+ }
12
+
13
+ item['children'] << { 'id' => 'agents' , 'href' => '/admin/agents' , 'text' => 'Agents' , 'modal' => false }
14
+ item['children'] << { 'id' => 'agents' , 'href' => '/admin/offices' , 'text' => 'Offices' , 'modal' => false }
15
+ item['children'] << { 'id' => 'open-houses' , 'href' => '/admin/open-houses' , 'text' => 'Open Houses' , 'modal' => false }
16
+ item['children'] << { 'id' => 'residential' , 'href' => '/admin/residential' , 'text' => 'Residential Property' , 'modal' => false }
17
+ item['children'] << { 'id' => 'commercial' , 'href' => '/admin/commercial' , 'text' => 'Commercial Property' , 'modal' => false }
18
+ item['children'] << { 'id' => 'commercial' , 'href' => '/admin/multi-family' , 'text' => 'Multi-Family Property' , 'modal' => false }
19
+ item['children'] << { 'id' => 'land' , 'href' => '/admin/land' , 'text' => 'Land Property' , 'modal' => false }
20
+
21
+ nav << item
22
+
23
+ return nav
24
+ end
25
+
26
+ end
@@ -0,0 +1,7 @@
1
+ <div class='top_right_controls'>
2
+ <input type='button' value='General' onclick="window.location='/admin/agents/<%= @agent.id %>/edit';" />
3
+ <input type='button' value='Bio' onclick="window.location='/admin/agents/<%= @agent.id %>/edit-bio';" />
4
+ <input type='button' value='Contact Info' onclick="window.location='/admin/agents/<%= @agent.id %>/edit-contact-info';" />
5
+ <input type='button' value='MLS Info' onclick="window.location='/admin/agents/<%= @agent.id %>/edit-mls-info';" />
6
+ </div>
7
+ <p>Agent: <%= "#{@agent.first_name} #{@agent.last_name}, #{@agent.la_code}" %></p>
@@ -0,0 +1,28 @@
1
+ <h1>Edit Agent</h1>
2
+ <%= render :partial => 'agents/admin_top_nav' %>
3
+
4
+ <div id='agent_<%= @agent.id %>_hide' ></div>
5
+ <div id='agent_<%= @agent.id %>_assistant_to' ></div>
6
+
7
+ <p style='clear: both;'><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
8
+
9
+ <% content_for :caboose_js do %>
10
+ <%= javascript_include_tag "caboose/model/all" %>
11
+ <script type='text/javascript'>
12
+ $(document).ready(function() {
13
+ m = new ModelBinder({
14
+ name: 'Agent',
15
+ id: <%= @agent.id %>,
16
+ update_url: '/admin/agents/<%= @agent.id %>',
17
+ authenticity_token: '<%= form_authenticity_token %>',
18
+ attributes: [
19
+ { name: 'hide' , nice_name: 'Hide from website' , type: 'checkbox' , value: <%= raw @agent.hide %>, width: 400 },
20
+ { name: 'assistant_to' , nice_name: 'Assistant To' , type: 'select' , value: <%= raw Caboose.json(@agent.assistant_to) %>, width: 400, text: <%= raw Caboose.json(@boss ? "#{@boss.first_name} #{@boss.last_name}" : 'empty') %>, options_url: '/admin/agents/assistant-to-options', empty_text: 'Not an assistant' }
21
+ ]
22
+ });
23
+ });
24
+ $(window).load(function() {
25
+ var modal = new CabooseModal(800);
26
+ });
27
+ </script>
28
+ <% end %>
@@ -0,0 +1,31 @@
1
+ <h1>Edit Agent</h1>
2
+ <%= render :partial => 'agents/admin_top_nav' %>
3
+
4
+ <div id='agent_<%= @agent.id %>_bio'></div>
5
+
6
+ <p style='clear: both;'><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
7
+
8
+ <% content_for :caboose_js do %>
9
+ <%= javascript_include_tag "caboose/model/all" %>
10
+ <script type='text/javascript'>
11
+ $(document).ready(function() {
12
+ m = new ModelBinder({
13
+ name: 'Agent',
14
+ id: <%= @agent.id %>,
15
+ update_url: '/admin/agents/<%= @agent.id %>',
16
+ authenticity_token: '<%= form_authenticity_token %>',
17
+ attributes: [{
18
+ name: 'bio',
19
+ nice_name: 'Bio',
20
+ type: 'textarea',
21
+ value: <%= raw Caboose.json(@agent.bio) %>,
22
+ width: 600,
23
+ height: 250
24
+ }]
25
+ });
26
+ });
27
+ $(window).load(function() {
28
+ var modal = new CabooseModal(800);
29
+ });
30
+ </script>
31
+ <% end %>
@@ -0,0 +1,31 @@
1
+ <h1>Edit Agent</h1>
2
+ <%= render :partial => 'agents/admin_top_nav' %>
3
+
4
+ <div id='agent_<%= @agent.id %>_contact_info' ></div>
5
+
6
+ <p style='clear: both;'><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
7
+
8
+ <% content_for :caboose_js do %>
9
+ <%= javascript_include_tag "caboose/model/all" %>
10
+ <script type='text/javascript'>
11
+ $(document).ready(function() {
12
+ m = new ModelBinder({
13
+ name: 'Agent',
14
+ id: <%= @agent.id %>,
15
+ update_url: '/admin/agents/<%= @agent.id %>',
16
+ authenticity_token: '<%= form_authenticity_token %>',
17
+ attributes: [{
18
+ name: 'contact_info',
19
+ nice_name: 'Contact Info',
20
+ type: 'textarea',
21
+ value: <%= raw Caboose.json(@agent.contact_info) %>,
22
+ width: 750,
23
+ height: 250
24
+ }]
25
+ });
26
+ });
27
+ $(window).load(function() {
28
+ var modal = new CabooseModal(800);
29
+ });
30
+ </script>
31
+ <% end %>
@@ -0,0 +1,71 @@
1
+ <h1>Edit Agent</h1>
2
+ <%= render :partial => 'agents/admin_top_nav' %>
3
+
4
+ <p>
5
+ <input type='button' value='< Back' onclick="window.location='/admin/agents';" />
6
+ <input type='button' value='Refresh from MLS' onclick="refresh_agent_from_mls(<%= @agent.id %>);" />
7
+ </p>
8
+ <div id='message'><%= raw flash[:message] ? flash[:message] : "" %></div>
9
+
10
+ <table class='data'>
11
+ <tr><td>beeper_phone </td><td><%= @agent.beeper_phone %></td></tr>
12
+ <tr><td>car_phone </td><td><%= @agent.car_phone %></td></tr>
13
+ <tr><td>date_created </td><td><%= @agent.date_created %></td></tr>
14
+ <tr><td>date_modified </td><td><%= @agent.date_modified %></td></tr>
15
+ <tr><td>defaultemail </td><td><%= @agent.defaultemail %></td></tr>
16
+ <tr><td>fax_phone </td><td><%= @agent.fax_phone %></td></tr>
17
+ <tr><td>first_name </td><td><%= @agent.first_name %></td></tr>
18
+ <tr><td>home_phone </td><td><%= @agent.home_phone %></td></tr>
19
+ <tr><td>la_code </td><td><%= @agent.la_code %></td></tr>
20
+ <tr><td>last_name </td><td><%= @agent.last_name %></td></tr>
21
+ <tr><td>lo_code </td><td><%= @agent.lo_code %></td></tr>
22
+ <tr><td>mail_addr1 </td><td><%= @agent.mail_addr1 %></td></tr>
23
+ <tr><td>mail_addr2 </td><td><%= @agent.mail_addr2 %></td></tr>
24
+ <tr><td>mail_city </td><td><%= @agent.mail_city %></td></tr>
25
+ <tr><td>mail_state </td><td><%= @agent.mail_state %></td></tr>
26
+ <tr><td>mail_zip </td><td><%= @agent.mail_zip %></td></tr>
27
+ <tr><td>member_email </td><td><%= @agent.member_email %></td></tr>
28
+ <tr><td>member_page </td><td><%= @agent.member_page %></td></tr>
29
+ <tr><td>member_status </td><td><%= @agent.member_status %></td></tr>
30
+ <tr><td>nrds_id </td><td><%= @agent.nrds_id %></td></tr>
31
+ <tr><td>office_phone </td><td><%= @agent.office_phone %></td></tr>
32
+ <tr><td>other_phone </td><td><%= @agent.other_phone %></td></tr>
33
+ <tr><td>phone_change_date </td><td><%= @agent.phone_change_date %></td></tr>
34
+ <tr><td>phone_direct_office </td><td><%= @agent.phone_direct_office %></td></tr>
35
+ <tr><td>phone_home_fax </td><td><%= @agent.phone_home_fax %></td></tr>
36
+ <tr><td>phone_pager </td><td><%= @agent.phone_pager %></td></tr>
37
+ <tr><td>phone_second_home </td><td><%= @agent.phone_second_home %></td></tr>
38
+ <tr><td>phone_toll_free </td><td><%= @agent.phone_toll_free %></td></tr>
39
+ <tr><td>phone_voice_mail </td><td><%= @agent.phone_voice_mail %></td></tr>
40
+ <tr><td>phone_voice_pager </td><td><%= @agent.phone_voice_pager %></td></tr>
41
+ <tr><td>photo_count </td><td><%= @agent.photo_count %></td></tr>
42
+ <tr><td>photo_date_modified </td><td><%= @agent.photo_date_modified %></td></tr>
43
+ </table>
44
+
45
+ <p><input type='button' value='< Back' onclick="window.location='/admin/agents';" /></p>
46
+
47
+ <% content_for :caboose_js do %>
48
+ <%= javascript_include_tag "caboose/model/all" %>
49
+ <script type='text/javascript'>
50
+
51
+ function refresh_agent_from_mls(agent_id)
52
+ {
53
+ //modal.autosize("<p class='loading'>Refreshing agent info from MLS...</p>");
54
+ $.ajax({
55
+ url: '/admin/agents/' + agent_id + '/refresh',
56
+ success: function(resp) {
57
+ if (resp.error)
58
+ modal.autosize("<p class='note error'>" + resp.error + "</p>");
59
+ if (resp.reload)
60
+ location.reload();
61
+ }
62
+ });
63
+ }
64
+
65
+ var modal = false;
66
+ $(window).load(function() {
67
+ modal = new CabooseModal(800);
68
+ });
69
+
70
+ </script>
71
+ <% end %>