caboose-rets 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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 %>