caboose-rets 0.1.183 → 0.1.184

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0685d8060e2893e21ce7813a2258f5987c0b522b5cf38c2703300fd9508f114f'
4
- data.tar.gz: 5055f63de96a36585c00614e26d4f4f5b13bcb5575c6147ed70a1f6722f0f682
3
+ metadata.gz: 84ef101eafb83b5891a32f9557f355e5f46de43e3d1e544aad19e5a533e78b6e
4
+ data.tar.gz: 1ddefc2dbff138dcb82eb3e4c879f9b19956726d2dd20ca134ec7106a45ce99e
5
5
  SHA512:
6
- metadata.gz: 35f1c82f2581745f2c38b3543964163649e9b3b5b4a3560dba4624f576567c7532fe4be14119c55b808d5bbc4403373957c95c0ab1a77f0d538e56a9127156e5
7
- data.tar.gz: 382a2e824f97e5f0827021d192dc0914f926e18a7e46bbc05655d4660a63efe2b5f427c98d3168d89c91b7c6cd83cea3e04edf0581cc3669b66a1ee2b70a4ef2
6
+ metadata.gz: 754a940a4a13708921c8e4b7bd05c311f04f14b448ac8cb6d6938c752f3f20960a7954465fa84530b3a9b0c8bc6b3cde2394414a6aa07981e5029e5b66aa5ce7
7
+ data.tar.gz: 80eace42b684e7bb8a25b4c7e88263c596fd1cdb2bd41e6fe709b260ec8401675c6fad0c26e56fc341eb247a103d30f69c3550d20a969b097a19df7b7bcd5605
@@ -11,7 +11,8 @@ module CabooseRets
11
11
  # GET /admin/users/:id/mls
12
12
  def rets_info
13
13
  @edituser = Caboose::User.where(:id => params[:id], :site_id => @site.id).first
14
- @saved = SavedProperty.where(:user_id => @edituser.id).order('date_saved desc').all
14
+ @saved = SavedProperty.where(:user_id => @edituser.id).order('date_saved desc').limit(100)
15
+ @emails = Notification.where(:user_id => @edituser.id).order('date_sent desc').limit(100)
15
16
  render :layout => 'caboose/admin'
16
17
  end
17
18
 
@@ -56,4 +56,76 @@ class CabooseRets::RetsMailer < ActionMailer::Base
56
56
  )
57
57
  end
58
58
 
59
+ def daily_report(user, new_listings, related_listings)
60
+ @user = user
61
+ @new_listings = new_listings
62
+ @related_listings = related_listings
63
+ @site = user.site
64
+ to_address = user.email
65
+ reply_to = @site.contact_email.blank? ? 'noreply@caboosecms.com' : @site.contact_email
66
+ @color = @site.theme ? @site.theme.color_main : @site.theme_color
67
+ @domain = "https://#{@site.primary_domain.domain}"
68
+ @domain = "http://dev.pmre.com:3000" if Rails.env.development?
69
+ @url = @domain
70
+ @url += "/real-estate" if @site.id == 541
71
+ @logo_url = @site.logo.url(:large)
72
+ subject = @site.id == 541 ? "New and Suggested Listings from Pritchett-Moore Real Estate" : "New and Suggested Listings from #{@site.description}"
73
+ @logo_url = "https:#{@logo_url}" if !@logo_url.include?('http')
74
+ @unsubscribe_url = "https://#{@site.primary_domain.domain}/rets-unsubscribe?token=7b8v9j#{@user.id}9b6h0c2n"
75
+ mail(
76
+ :to => to_address,
77
+ :from => from_address(@site.id, nil),
78
+ :subject => subject,
79
+ :reply_to => reply_to
80
+ )
81
+ end
82
+
83
+ def property_status_change(user, property, old_status)
84
+ @user = user
85
+ @property = property
86
+ @old_status = old_status
87
+ @site = user.site
88
+ to_address = user.email
89
+ reply_to = @site.contact_email.blank? ? 'noreply@caboosecms.com' : @site.contact_email
90
+ @color = @site.theme ? @site.theme.color_main : @site.theme_color
91
+ @domain = "https://#{@site.primary_domain.domain}"
92
+ @domain = "http://dev.pmre.com:3000" if Rails.env.development?
93
+ @url = @domain
94
+ @url += "/real-estate" if @site.id == 541
95
+ @logo_url = @site.logo.url(:large)
96
+ subject = "Status Change for Listing MLS ##{@property.mls_number}"
97
+ @logo_url = "https:#{@logo_url}" if !@logo_url.include?('http')
98
+ @unsubscribe_url = "https://#{@site.primary_domain.domain}/rets-unsubscribe?token=7b8v9j#{@user.id}9b6h0c2n"
99
+ mail(
100
+ :to => to_address,
101
+ :from => from_address(@site.id, nil),
102
+ :subject => subject,
103
+ :reply_to => reply_to
104
+ )
105
+ end
106
+
107
+ def property_price_change(user, property, old_price)
108
+ @user = user
109
+ @property = property
110
+ @old_price = old_price
111
+ @site = user.site
112
+ to_address = user.email
113
+ reply_to = @site.contact_email.blank? ? 'noreply@caboosecms.com' : @site.contact_email
114
+ @color = @site.theme ? @site.theme.color_main : @site.theme_color
115
+ @domain = "https://#{@site.primary_domain.domain}"
116
+ @domain = "http://dev.pmre.com:3000" if Rails.env.development?
117
+ @url = @domain
118
+ @url += "/real-estate" if @site.id == 541
119
+ @logo_url = @site.logo.url(:large)
120
+ subject = "Price Change for Listing MLS ##{@property.mls_number}"
121
+ @logo_url = "https:#{@logo_url}" if !@logo_url.include?('http')
122
+ @unsubscribe_url = "https://#{@site.primary_domain.domain}/rets-unsubscribe?token=7b8v9j#{@user.id}9b6h0c2n"
123
+ mail(
124
+ :to => to_address,
125
+ :from => from_address(@site.id, nil),
126
+ :subject => subject,
127
+ :reply_to => reply_to
128
+ )
129
+ end
130
+
59
131
  end
@@ -0,0 +1,206 @@
1
+ class CabooseRets::Notification < ActiveRecord::Base
2
+
3
+ self.table_name = "rets_notifications"
4
+
5
+ belongs_to :user, :class_name => "Caboose::User"
6
+ belongs_to :site, :class_name => "Caboose::Site"
7
+
8
+ def self.property_status_changed(property, old_status)
9
+ return if property.nil?
10
+
11
+ us = Caboose::Setting.where(:site_id => 541, :name => "test_usernames").first
12
+ allowed_users = us ? us.value : ""
13
+ allowed_users = 'billyswifty' if Rails.env.development?
14
+ uwhere = allowed_users.blank? ? "" : "('#{allowed_users}' ILIKE '%' || username || '%')"
15
+
16
+ user_ids = CabooseRets::SavedProperty.where(:mls_number => property.mls_number).pluck(:user_id)
17
+ if user_ids.count > 0
18
+ user_ids.each do |user_id|
19
+ user = Caboose::User.where(uwhere).where(:id => user_id, :tax_exempt => false).first
20
+ d1 = DateTime.now - 24.hours
21
+ if user
22
+ # Check if a similar notification has already been sent
23
+ n = CabooseRets::Notification.where(
24
+ :user_id => user.id,
25
+ :site_id => user.site_id,
26
+ :kind => "Property Status Changed",
27
+ :sent_to => user.email,
28
+ :object_kind => "Property",
29
+ :object_id => property.mls_number,
30
+ :old_value => old_status,
31
+ :new_value => property.status
32
+ ).where("date_sent >= ?", d1).first
33
+ if n.nil?
34
+ n = CabooseRets::Notification.create(
35
+ :user_id => user.id,
36
+ :site_id => user.site_id,
37
+ :date_sent => DateTime.now,
38
+ :kind => "Property Status Changed",
39
+ :sent_to => user.email,
40
+ :object_kind => "Property",
41
+ :object_id => property.mls_number,
42
+ :old_value => old_status,
43
+ :new_value => property.status
44
+ )
45
+ CabooseRets::RetsMailer.configure_for_site(user.site_id).property_status_change(user, property, old_status).deliver_later
46
+ else
47
+ puts "Found a duplicate notification, not sending..."
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ def self.property_price_changed(property, old_price)
55
+ return if property.nil? || property.status != 'Active'
56
+
57
+ us = Caboose::Setting.where(:site_id => 541, :name => "test_usernames").first
58
+ allowed_users = us ? us.value : ""
59
+ allowed_users = 'billyswifty' if Rails.env.development?
60
+ uwhere = allowed_users.blank? ? "" : "('#{allowed_users}' ILIKE '%' || username || '%')"
61
+
62
+ user_ids = CabooseRets::SavedProperty.where(:mls_number => property.mls_number).pluck(:user_id)
63
+ if user_ids.count > 0
64
+ user_ids.each do |user_id|
65
+ user = Caboose::User.where(uwhere).where(:id => user_id, :tax_exempt => false).first
66
+ d1 = DateTime.now - 24.hours
67
+ if user
68
+ # Check if a similar notification has already been sent
69
+ n = CabooseRets::Notification.where(
70
+ :user_id => user.id,
71
+ :site_id => user.site_id,
72
+ :kind => "Property Price Changed",
73
+ :sent_to => user.email,
74
+ :object_kind => "Property",
75
+ :object_id => property.mls_number,
76
+ :old_value => old_price,
77
+ :new_value => property.list_price
78
+ ).where("date_sent >= ?", d1).first
79
+ if n.nil?
80
+ n = CabooseRets::Notification.create(
81
+ :user_id => user.id,
82
+ :site_id => user.site_id,
83
+ :date_sent => DateTime.now,
84
+ :kind => "Property Price Changed",
85
+ :sent_to => user.email,
86
+ :object_kind => "Property",
87
+ :object_id => property.mls_number,
88
+ :old_value => old_price,
89
+ :new_value => property.list_price
90
+ )
91
+ CabooseRets::RetsMailer.configure_for_site(user.site_id).property_price_change(user, property, old_price).deliver_later
92
+ else
93
+ puts "Found a duplicate notification, not sending..."
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def self.send_new_suggested_emails
101
+ roles = Caboose::Role.where(:name => "RETS Visitor").order(:id).all
102
+ if roles.count > 0
103
+ role_ids = roles.map{|r| r.id}
104
+
105
+ us = Caboose::Setting.where(:site_id => 541, :name => "test_usernames").first
106
+ allowed_users = us ? us.value : ""
107
+ allowed_users = 'billyswifty' if Rails.env.development?
108
+ uwhere = allowed_users.blank? ? "" : "('#{allowed_users}' ILIKE '%' || username || '%')"
109
+
110
+ users = Caboose::User.joins(:role_memberships).where(uwhere).where("role_memberships.role_id in (?)", role_ids).where(:tax_exempt => false).order(:id).all
111
+
112
+ if users.count > 0
113
+
114
+ new_listings = CabooseRets::Property.where(:status => 'Active', :property_type => 'Residential').order('original_entry_timestamp desc').take(3)
115
+
116
+ users.each do |user|
117
+
118
+ puts "Gathering data for user: #{user.username}" if Rails.env.development?
119
+
120
+ saved_mls = CabooseRets::SavedProperty.where(:user_id => user.id).pluck(:mls_number)
121
+ saved_properties = saved_mls && saved_mls.count > 0 ? CabooseRets::Property.where(:status => 'Active', :property_type => 'Residential').where(:mls_number => saved_mls).limit(100) : []
122
+
123
+ if saved_properties.count > 0
124
+
125
+ puts "Saved listings: #{saved_properties.count}" if Rails.env.development?
126
+
127
+ price_where = "list_price is not null and (list_price >= ? AND list_price <= ?)"
128
+ beds_where = "beds_total is not null and (beds_total >= ? AND beds_total <= ?)"
129
+
130
+ all_prices = saved_properties.map{|p| p.list_price}
131
+ price_min = all_prices.count > 0 ? (all_prices.min * 0.8) : 150000
132
+ price_max = all_prices.count > 0 ? (all_prices.max * 1.2) : 350000
133
+
134
+ puts "Price range: #{price_min} - #{price_max}" if Rails.env.development?
135
+
136
+ all_beds = saved_properties.map{|p| p.beds_total}
137
+ beds_min = all_beds.count > 0 ? (all_beds.min - 1) : 2
138
+ beds_max = all_beds.count > 0 ? (all_beds.max + 1) : 5
139
+
140
+ puts "Beds range: #{beds_min} - #{beds_max}" if Rails.env.development?
141
+
142
+ property_subtypes = []
143
+ property_areas = []
144
+
145
+ saved_properties.each do |sp|
146
+ property_subtypes << sp.property_subtype if !property_subtypes.include?(sp.property_subtype)
147
+ property_areas << sp.area if !property_areas.include?(sp.area)
148
+ end
149
+
150
+ puts "Property subtypes: #{property_subtypes}" if Rails.env.development?
151
+ puts "Property areas: #{property_areas}" if Rails.env.development?
152
+
153
+ related_listings = CabooseRets::Property.where(:property_type => 'Residential', :status => 'Active', :property_subtype => property_subtypes, :area => property_areas).where("mls_number not in (?)", saved_mls).where(price_where,price_min,price_max).where(beds_where,beds_min,beds_max).order('original_entry_timestamp desc').take(3)
154
+
155
+ else
156
+
157
+ related_listings = []
158
+
159
+ end
160
+
161
+ if new_listings.count > 0 || related_listings.count > 0
162
+
163
+ msg = ""
164
+
165
+ if new_listings.count > 0
166
+ mls1 = new_listings.map{ |l| l.mls_number }
167
+ msg += "New Listings: #{mls1.join(', ')}"
168
+ end
169
+
170
+ if related_listings.count > 0
171
+ mls2 = related_listings.map{ |l| l.mls_number }
172
+ msg += "\n" if new_listings.count > 0
173
+ msg += "Related Listings: #{mls2.join(', ')}"
174
+ end
175
+
176
+ d = DateTime.now - 7.days
177
+ n = CabooseRets::Notification.where(
178
+ :user_id => user.id,
179
+ :site_id => user.site_id,
180
+ :kind => "New and Suggested Listings",
181
+ :sent_to => user.email,
182
+ :message => msg
183
+ ).where("date_sent >= ?", d).first
184
+
185
+ if n.nil?
186
+ n = CabooseRets::Notification.create(
187
+ :user_id => user.id,
188
+ :site_id => user.site_id,
189
+ :date_sent => DateTime.now,
190
+ :kind => "New and Suggested Listings",
191
+ :sent_to => user.email,
192
+ :message => msg
193
+ )
194
+ CabooseRets::RetsMailer.configure_for_site(user.site_id).daily_report(user, new_listings, related_listings).deliver_later
195
+ else
196
+ puts "Found a duplicate notification, not sending..."
197
+ end
198
+
199
+ end
200
+
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ end
@@ -24,10 +24,12 @@ class CabooseRets::Property <ActiveRecord::Base
24
24
  m = Caboose::Media.where(:id => img.media_id).first
25
25
  if m && m.image && m.image.url(:large)
26
26
  img_url = m.image.url(:large)
27
+ img_url = "https:#{img_url}" if !img_url.include?('http')
27
28
  return img_url
28
29
  break
29
30
  end
30
31
  end
32
+ img_url = "https:#{img_url}" if !img_url.include?('http')
31
33
  return img_url
32
34
  end
33
35
 
@@ -55,6 +57,10 @@ class CabooseRets::Property <ActiveRecord::Base
55
57
  end
56
58
 
57
59
  def parse(data)
60
+
61
+ old_price = self.list_price
62
+ old_status = self.status
63
+
58
64
  # puts(data.to_s)
59
65
  # self.access = nil
60
66
  self.acreage = data['LotSizeAcres'].blank? ? nil : data['LotSizeAcres'].to_f
@@ -249,5 +255,14 @@ class CabooseRets::Property <ActiveRecord::Base
249
255
  self.zoning = data['Zoning']
250
256
  # self.zoning_northport = data['ZoningNorthPort']
251
257
  # self.zoning_tusc = data['ZoningTusc']
258
+
259
+
260
+ if old_status != self.status # status was changed
261
+ CabooseRets::Notification.delay(:queue => "rets").property_status_changed(self, old_status)
262
+ elsif old_price != self.list_price && self.status == 'Active' # price was changed
263
+ CabooseRets::Notification.delay(:queue => "rets").property_price_changed(self, old_price)
264
+ end
265
+
266
+
252
267
  end
253
268
  end
@@ -70,7 +70,6 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
70
70
  :search_type => m.search_type,
71
71
  :class => class_type,
72
72
  :query => query,
73
- # :limit => 3,
74
73
  :timeout => -1
75
74
  }
76
75
  obj = nil
@@ -135,7 +134,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
135
134
 
136
135
  statusquery = ""
137
136
  case class_type
138
- when 'Property' then statusquery = "MlsStatus=Active"
137
+ when 'Property' then statusquery = "OriginatingSystemName=WESTAL"
139
138
  when 'Office' then statusquery = "OfficeStatus=Active"
140
139
  when 'Member' then statusquery = "MemberStatus=Active"
141
140
  when 'OpenHouse' then statusquery = "OpenHouseKeyNumeric=0+"
@@ -164,7 +163,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
164
163
  end
165
164
 
166
165
  # Check for changed images
167
- if class_type == 'Property'
166
+ if class_type == 'Property' && Rails.env.production?
168
167
  self.log3("Property",nil,"Checking for modified images on Properties...")
169
168
  d1 = (self.last_updated - 1.hours).in_time_zone(CabooseRets::timezone).strftime("%FT%T")
170
169
  params = {
@@ -191,17 +190,6 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
191
190
  # Single model import methods (called from a worker dyno)
192
191
  #=============================================================================
193
192
 
194
- # def self.import_property(mui, save_images = true)
195
- # self.import('Listing', "(Matrix_Unique_ID=#{mui})")
196
- # p = CabooseRets::Property.where(:matrix_unique_id => mui.to_s).first
197
- # if p != nil
198
- # self.download_property_images(p)
199
- # self.update_coords(p)
200
- # else
201
- # self.log("No Property associated with #{mui}")
202
- # end
203
- # end
204
-
205
193
  def self.import_properties(mls_id, save_images = true)
206
194
  si = save_images ? 'saving images' : 'not saving images'
207
195
  self.log3('Property',mls_id,"Importing Property #{mls_id} and #{si}...")
@@ -209,12 +197,12 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
209
197
  self.import('Property', "(ListingId=#{mls_id})")
210
198
  p = CabooseRets::Property.where(:mls_number => mls_id.to_s).first
211
199
  if p != nil && p.status == 'Active'
212
- self.download_property_images(p) if save_images == true
200
+ self.download_property_images(p) if save_images == true && Rails.env.production?
213
201
  if p.latitude.blank? || p.latitude == '0.0' || p.longitude.blank? || p.longitude == '0.0'
214
202
  self.update_coords(p)
215
203
  end
216
204
  else
217
- self.log3(nil,nil,"No Property associated with #{mls_id}")
205
+ self.log3(nil,nil,"No Active Property associated with #{mls_id}, not downloading images")
218
206
  end
219
207
  end
220
208
 
@@ -265,43 +253,8 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
265
253
  # Images go here
266
254
  #=============================================================================
267
255
 
268
- # def self.download_property_images(p, save_images = true)
269
- # return if save_images == false
270
- # self.log("- Downloading GFX records for #{p.matrix_unique_id}...")
271
- # params = {
272
- # :search_type => 'Media',
273
- # :class => 'Photo',
274
- # :type => 'Photo',
275
- # :resource => 'Property',
276
- # :query => "(ID=*#{p.matrix_unique_id}:1*)",
277
- # :limit => 1000,
278
- # :timeout => -1
279
- # }
280
- # ids = []
281
- # self.client.search(params) do |data|
282
- # puts data
283
- # ids << data['MEDIA_ID']
284
- # m = CabooseRets::Media.where(:media_id => data['MEDIA_ID']).first
285
- # m = CabooseRets::Media.new if m.nil?
286
- # data.MEDIA_MUI = p.matrix_unique_id
287
- # m.parse(data)
288
- # m.save
289
- # end
290
- # if ids.count > 0
291
- # # Delete any records in the local database that shouldn't be there
292
- # self.log("- Deleting GFX records for MLS ##{p.matrix_unique_id} in the local database that are not in the remote database...")
293
- # query = "select media_id from rets_media where matrix_unique_id = '#{p.matrix_unique_id}'"
294
- # rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
295
- # local_ids = rows.collect{ |row| row['media_id'] }
296
- # ids_to_remove = local_ids - ids
297
- # if ids_to_remove && ids_to_remove.count > 0
298
- # query = ["delete from rets_media where media_id in (?)", ids_to_remove]
299
- # ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
300
- # end
301
- # end
302
- # end
303
-
304
256
  def self.download_property_images(p)
257
+ return if Rails.env.development?
305
258
  self.log3('Property',p.mls_number,"Downloading images for #{p.mls_number}...")
306
259
  ids_to_keep = []
307
260
  begin
@@ -369,93 +322,21 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
369
322
  end
370
323
  end
371
324
 
372
- # # Get first image
373
- # self.client.get_object(:resource => 'Property', :type => 'Photo', :location=> false, :id => "#{p.matrix_unique_id}:0") do |headers, content|
374
- # self.log3('Media',p.mls_number,"Downloading first photo with content-id #{headers['content-id']}, orderhint #{headers['orderhint']}, object-id #{headers['object-id']}")
375
- # m = CabooseRets::Media.where(:media_mui => headers['content-id'], :media_order => 0).first
376
- # m = CabooseRets::Media.new if m.nil?
377
- # tmp_path = "#{Rails.root}/tmp/rets_media_#{headers['content-id']}:0.jpeg"
378
- # File.open(tmp_path, "wb") do |f|
379
- # f.write(content)
380
- # end
381
- # m.media_mui = headers['content-id']
382
- # m.media_order = 0
383
- # m.media_type = 'Photo'
384
- # cm = Caboose::Media.new
385
- # cm.image = File.open(tmp_path)
386
- # cm.name = "rets_media_#{headers['content-id']}_0"
387
- # cm.original_name = "rets_media_#{headers['content-id']}_0.jpeg"
388
- # cm.processed = true
389
- # cm.save
390
- # m.media_id = cm.id
391
- # m.save
392
- # self.log3("Media",p.mls_number,"Created new RetsMedia object #{m.id}, CabooseMedia object #{cm.id}")
393
- # `rm #{tmp_path}`
394
- # self.log3("Media",p.mls_number,"Image rets_media_#{headers['content-id']}_0 saved")
395
- # end
396
- # # Get rest of images
397
- # self.client.get_object(:resource => 'Property', :type => 'Photo', :location=> false, :id => "#{p.matrix_unique_id}:*") do |headers, content|
398
- # self.log3('Media',p.mls_number,"Downloading subsequent photo with content-id #{headers['content-id']}, orderhint #{headers['orderhint']}, object-id #{headers['object-id']}")
399
- # m = CabooseRets::Media.where(:media_mui => headers['content-id'], :media_order => headers['orderhint']).first
400
- # m = CabooseRets::Media.new if m.nil?
401
- # tmp_path = "#{Rails.root}/tmp/rets_media_#{headers['content-id']}:#{headers['object-id']}.jpeg"
402
- # File.open(tmp_path, "wb") do |f|
403
- # f.write(content)
404
- # end
405
- # m.media_mui = headers['content-id']
406
- # m.media_order = headers['orderhint']
407
- # m.media_type = 'Photo'
408
- # cm = Caboose::Media.new
409
- # cm.image = File.open(tmp_path)
410
- # cm.name = "rets_media_#{headers['content-id']}_#{headers['object-id']}"
411
- # cm.original_name = "rets_media_#{headers['content-id']}_#{headers['object-id']}.jpeg"
412
- # cm.processed = true
413
- # cm.save
414
- # m.media_id = cm.id
415
- # m.save
416
- # self.log3("Media",p.mls_number,"Created new RetsMedia object #{m.id}, CabooseMedia object #{cm.id}")
417
- # `rm #{tmp_path}`
418
- # self.log3("Media",p.mls_number,"Image rets_media_#{headers['content-id']}_#{headers['object-id']} saved")
419
- # end
420
- # rescue RETS::APIError => err
421
- # self.log "No image for #{p.mls_number}."
422
- # self.log err
423
- # end
424
325
  end
425
326
 
426
327
  def self.download_missing_images
427
328
  self.log3("Property",nil,"Downloading all missing images...")
428
- CabooseRets::Property.where("photo_count = ? OR photo_count is null", '').all.each do |p|
329
+ CabooseRets::Property.where("photo_count = ? OR photo_count is null", '').where(:status => "Active").all.each do |p|
429
330
  self.delay(:priority => 10, :queue => 'rets').import_properties(p.mls_number, true)
430
331
  end
431
332
  end
432
333
 
433
334
  def self.download_agent_image(agent)
434
- # self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
435
- # begin
436
- # self.client.get_object(:resource => :Member, :type => :Photo, :location => true, :id => property.list_agent_mls_id) do |headers, content|
437
- # agent.verify_meta_exists
438
- # agent.meta.image_location = headers['location']
439
- # agent.meta.save
440
- # end
441
- # rescue RETS::APIError => err
442
- # self.log "No image for #{agent.first_name} #{agent.last_name}."
443
- # self.log err
444
- # end
335
+
445
336
  end
446
337
 
447
338
  def self.download_office_image(office)
448
- #self.log "Saving image for #{agent.first_name} #{agent.last_name}..."
449
- #begin
450
- # self.client.get_object(:resource => :Agent, :type => :Photo, :location => true, :id => agent.la_code) do |headers, content|
451
- # agent.verify_meta_exists
452
- # agent.meta.image_location = headers['location']
453
- # agent.meta.save
454
- # end
455
- #rescue RETS::APIError => err
456
- # self.log "No image for #{agent.first_name} #{agent.last_name}."
457
- # self.log err
458
- #end
339
+
459
340
  end
460
341
 
461
342
  #=============================================================================
@@ -517,6 +398,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
517
398
  def self.purge_open_houses() self.delay(:priority => 10, :queue => 'rets').purge_helper('OpenHouse', '2012-01-01') end
518
399
 
519
400
 
401
+ # Adds/removes records in the database
520
402
  def self.purge_helper(class_type, date_modified)
521
403
  m = self.meta(class_type)
522
404
  self.log(m.search_type)
@@ -573,12 +455,12 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
573
455
  ids_to_remove = local_ids - ids
574
456
  self.log3(class_type,nil,"Found #{ids_to_remove.count} #{class_type} records in the local database that are not in the remote database.")
575
457
 
576
- # Delete all RetsMedia and CabooseMedia for the deleted property listings
458
+ # Delete all RetsMedia and CabooseMedia for the deleted property listings (except keep the first image)
577
459
  if class_type == 'Property' && ids_to_remove && ids_to_remove.count > 0
578
460
  self.log3(class_type,nil,"Deleting Media objects that shouldn't be there...")
579
461
  muis = CabooseRets::Property.where("#{k} in (?)", ids_to_remove).pluck(:matrix_unique_id)
580
- if muis && muis.count > 0
581
- CabooseRets::Media.where("media_mui in (?)", muis).each do |med|
462
+ if muis && muis.count > 0 && Rails.env.production?
463
+ CabooseRets::Media.where("media_mui in (?)", muis).where("media_order != ?", 1).each do |med|
582
464
  self.log3("Media",med.id,"Deleting old RetsMedia #{med.id} and CabooseMedia #{med.media_id}...")
583
465
  m = Caboose::Media.where(:id => med.media_id).where("name ILIKE ?","rets_media%").first
584
466
  m.destroy if m
@@ -587,9 +469,11 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
587
469
  end
588
470
  end
589
471
 
590
- self.log3(class_type,nil,"Deleting #{class_type} records in the local database that shouldn't be there...")
591
- query = ["delete from #{t} where #{k} in (?)", ids_to_remove]
592
- ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
472
+ if class_type != 'Property' # keep all properties in the DB
473
+ self.log3(class_type,nil,"Deleting #{class_type} records in the local database that shouldn't be there...")
474
+ query = ["delete from #{t} where #{k} in (?)", ids_to_remove]
475
+ ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
476
+ end
593
477
 
594
478
  # Find any ids in the remote database that should be in the local database
595
479
  self.log3(class_type,nil,"Finding #{class_type} records in the remote database that should be in the local database...")
@@ -612,54 +496,6 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
612
496
  end
613
497
  end
614
498
 
615
- # def self.get_media_urls
616
- # m = self.meta(class_type)
617
-
618
- # # Get the total number of records
619
- # params = {
620
- # :search_type => m.search_type,
621
- # :class => class_type,
622
- # :query => "(#{m.matrix_modified_dt}=#{date_modified}T00:00:01+)",
623
- # :standard_names_only => true,
624
- # :timeout => -1
625
- # }
626
- # self.client.search(params.merge({ :count => 1 }))
627
- # count = self.client.rets_data[:code] == "20201" ? 0 : self.client.rets_data[:count]
628
- # batch_count = (count.to_f/5000.0).ceil
629
-
630
- # ids = []
631
- # k = m.remote_key_field
632
- # (0...batch_count).each do |i|
633
- # self.client.search(params.merge({ :select => [k], :limit => 5000, :offset => 5000*i })) do |data|
634
- # ids << data[k]
635
- # end
636
- # end
637
-
638
- # if ids.count > 0
639
- # # Delete any records in the local database that shouldn't be there
640
- # t = m.local_table
641
- # k = m.local_key_field
642
- # query = ["delete from #{t} where #{k} not in (?)", ids]
643
- # ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
644
-
645
- # # Find any ids in the remote database that should be in the local database
646
- # query = "select distinct #{k} from #{t}"
647
- # rows = ActiveRecord::Base.connection.select_all(ActiveRecord::Base.send(:sanitize_sql_array, query))
648
- # local_ids = rows.collect{ |row| row[k] }
649
- # ids_to_add = ids - local_ids
650
- # ids_to_add.each do |id|
651
- # self.log("Importing #{id}...")
652
- # case class_type
653
- # when "Property" then self.delay(:priority => 10, :queue => 'rets').import_properties(id, true)
654
- # when "Office" then self.delay(:priority => 10, :queue => 'rets').import_office(id, false)
655
- # when "Member" then self.delay(:priority => 10, :queue => 'rets').import_agent(id, false)
656
- # when "OpenHouse" then self.delay(:priority => 10, :queue => 'rets').import_open_house(id, false)
657
- # end
658
- # end
659
- # end
660
-
661
- # end
662
-
663
499
  #=============================================================================
664
500
  # Logging
665
501
  #=============================================================================
@@ -704,7 +540,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
704
540
  overlap = 1.week
705
541
  end
706
542
  self.update_after((self.last_updated - overlap), false)
707
- self.download_missing_images
543
+ self.download_missing_images if Rails.env.production?
708
544
  self.log3(nil,nil,"Saving the timestamp for when we updated to #{task_started.to_s}...")
709
545
  self.save_last_updated(task_started)
710
546
  self.log2("Unlocking the task...")
@@ -725,7 +561,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
725
561
  end
726
562
 
727
563
  # Delete RETS logs over 7 days old
728
- dt = DateTime.now - 7.days
564
+ dt = DateTime.now - 5.days
729
565
  sql = "delete from rets_logs where timestamp < '#{dt}';"
730
566
  ActiveRecord::Base.connection.select_all(sql)
731
567
 
@@ -347,6 +347,18 @@ class CabooseRets::Schema < Caboose::Utilities::Schema
347
347
  Caboose::User => [
348
348
  [ :rets_agent_mls_id , :string ]
349
349
  ],
350
+ CabooseRets::Notification => [
351
+ [ :user_id, :integer ],
352
+ [ :date_sent, :datetime ],
353
+ [ :site_id, :integer ],
354
+ [ :kind, :string ],
355
+ [ :sent_to, :string ],
356
+ [ :object_kind, :string ],
357
+ [ :object_id, :string ],
358
+ [ :old_value, :string ],
359
+ [ :new_value, :string ],
360
+ [ :message, :text ]
361
+ ],
350
362
  CabooseRets::RetsConfig => [
351
363
  [ :site_id, :integer ],
352
364
  [ :office_mls, :string ],
@@ -0,0 +1,31 @@
1
+ <table border="0" cellpadding="0" cellspacing="0" width="800" id="templateColumns" style="width:100%;margin:0 0 20px 0;text-align:left;">
2
+ <tr>
3
+ <td align="left" valign="top" width="25%" class="templateColumnContainer" style="width:25%;padding:0;">
4
+ <a style="display:block;text-decoration:none;" href="<%= url %>/properties/<%= p.mls_number %>/details">
5
+ <% if p.featured_photo_url %>
6
+ <img style="display:block;max-width:200px;height:auto;" width="200" alt="MLS # <%= p.mls_number %>" src="<%= p.featured_photo_url %>" />
7
+ <% end %>
8
+ </a>
9
+ </td>
10
+ <td align="left" valign="top" width="37.5%" class="templateColumnContainer" style="width:37.5%;padding:5px 5px 5px 10px;">
11
+ <p style="margin:0 0 5px 0;font-size:14px;line-height:16px;"><strong>MLS#: <%= p.mls_number %></strong></p>
12
+ <address style="margin:0 0 5px 0;font-size:15px;line-height:17px;"><%== p.full_address_city %></address>
13
+ <p style="margin:0 0 5px 0;font-size:15px;line-height:17px;">
14
+ <% if !p.subdivision.blank? %><span><%= p.subdivision.titleize %></span> | <% end %>
15
+ <% if !p.city.blank? && p.city.upcase != "NONE" %><span><%= p.city.titleize %></span><% end %>
16
+ </p>
17
+ </td>
18
+ <td align="left" valign="top" width="37.5%" class="templateColumnContainer" style="width:37.5%;padding:5px 0 5px 10px;">
19
+ <p style="margin:0 0 5px 0;font-size:16px;line-height:18px;"><strong><%= number_to_currency(p.list_price, :precision => 0) %></strong></p>
20
+ <p style="margin:0 0 5px 0;font-size:15px;line-height:17px;">
21
+ <% if !p.beds_total.blank? %><span><strong><%= p.beds_total %></strong> beds</span><br /><% end %>
22
+ <% if !p.baths_full.blank? %><span><strong><%= p.baths_full %></strong> baths</span><br /><% end %>
23
+ <% if !p.baths_half.blank? && p.baths_half > 0 %><span><strong><%= p.baths_half %></strong> ½ baths</span><br /><% end %>
24
+ <% if !p.sqft_total.blank? %><span><strong><%= number_with_delimiter(p.sqft_total.to_i, :delimiter => ',') %></strong> sqft</span><% end %>
25
+ </p>
26
+ <% if !p.original_entry_timestamp.blank? %>
27
+ <p style="margin:0;font-size:13px;line-height:15px;">Listed <%= time_ago_in_words(p.original_entry_timestamp) %> ago</p>
28
+ <% end %>
29
+ </td>
30
+ </tr>
31
+ </table>
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <title></title>
6
+ <style>
7
+ @media only screen and (max-width: 480px) {
8
+ #templateColumns{
9
+ width: 100% !important;
10
+ }
11
+ .templateColumnContainer{
12
+ display: block !important;
13
+ width: 100% !important;
14
+ padding: 10px !important;
15
+ }
16
+ }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable">
21
+ <tr>
22
+ <td align="center" valign="top">
23
+ <table border="0" cellpadding="20" cellspacing="0" width="800" id="emailContainer">
24
+ <tr>
25
+ <td align="center" valign="top">
26
+
27
+
28
+
29
+ <div style="text-align:center;margin-bottom:20px;padding:20px;background-color:<%= @color %>;">
30
+ <a style="display:inline-block;text-decoration:none;" href="<%= @url %>" target="_blank">
31
+ <img style="display:block;margin:0;" src="<%= @logo_url %>" alt="<%= @site.description %>" width="220" />
32
+ </a>
33
+ </div>
34
+
35
+ <div style="text-align:center;padding:20px;">
36
+ <h2>New and Suggested Listings</h2>
37
+
38
+ <% if @new_listings.count > 0 %>
39
+ <h3>New Listings</h3>
40
+ <% @new_listings.each do |prop| %>
41
+ <%== render :partial => "caboose_rets/rets_mailer/property_row", :locals => { :p => prop, :url => @domain } %>
42
+ <% end %>
43
+ <div style="padding:10px 10px 40px 10px;text-align:center;">
44
+ <a style="display:inline-block;border-radius:5px;background:<%= @color %>;color:#fff;padding:5px 15px;line-height:30px;text-decoration:none;font-size:15px;" target="_blank" href="<%= @url %>">See More New Listings</a>
45
+ </div>
46
+ <% end %>
47
+
48
+ <% if @related_listings.count > 0 %>
49
+ <h3>Suggested Listings</h3>
50
+ <% @related_listings.each do |prop| %>
51
+ <%== render :partial => "caboose_rets/rets_mailer/property_row", :locals => { :p => prop, :url => @domain } %>
52
+ <% end %>
53
+ <div style="padding:10px 10px 40px 10px;text-align:center;">
54
+ <a style="display:inline-block;border-radius:5px;background:<%= @color %>;color:#fff;padding:5px 15px;line-height:30px;text-decoration:none;font-size:15px;" target="_blank" href="<%= @domain %>/saved-properties">See My Saved Listings</a>
55
+ </div>
56
+ <% end %>
57
+
58
+ </div>
59
+
60
+ <div style="text-align:center;margin-top:20px;padding:20px;background-color:<%= @color %>;">
61
+ <p style="margin:0;font-size:13px;">
62
+ <a style="color:#fff;text-decoration:none;font-size:13px;display:inline-block;" target="_blank" href="<%= @unsubscribe_url %>">
63
+ Unsubscribe
64
+ </a>
65
+ </p>
66
+ </div>
67
+
68
+ </td>
69
+ </tr>
70
+ </table>
71
+ </td>
72
+ </tr>
73
+ </table>
74
+ </body>
75
+ </html>
76
+
@@ -0,0 +1,69 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <title></title>
6
+ <style>
7
+ @media only screen and (max-width: 480px) {
8
+ #templateColumns{
9
+ width: 100% !important;
10
+ }
11
+ .templateColumnContainer{
12
+ display: block !important;
13
+ width: 100% !important;
14
+ padding: 10px !important;
15
+ }
16
+ }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable">
21
+ <tr>
22
+ <td align="center" valign="top">
23
+ <table border="0" cellpadding="20" cellspacing="0" width="800" id="emailContainer">
24
+ <tr>
25
+ <td align="center" valign="top">
26
+
27
+
28
+
29
+ <div style="text-align:center;margin-bottom:20px;padding:20px;background-color:<%= @color %>;">
30
+ <a style="display:inline-block;text-decoration:none;" href="<%= @url %>" target="_blank">
31
+ <img style="display:block;margin:0;" src="<%= @logo_url %>" alt="<%= @site.description %>" width="220" />
32
+ </a>
33
+ </div>
34
+
35
+ <div style="text-align:center;padding:20px;">
36
+ <h2>Price Changed</h2>
37
+
38
+ <% if @property %>
39
+ <%== render :partial => "caboose_rets/rets_mailer/property_row", :locals => { :p => @property, :url => @domain } %>
40
+ <div style="padding:0 10px;text-align:center;">
41
+ <p style="margin:0 0 6px 0;">
42
+ <strong>Old Price</strong>: <%= number_to_currency(@old_price, :precision => 0) %>
43
+ </p>
44
+ <p style="margin:0;">
45
+ <strong>New Price</strong>: <%= number_to_currency(@property.list_price, :precision => 0) %>
46
+ </p>
47
+ </div>
48
+ <% end %>
49
+
50
+
51
+ </div>
52
+
53
+ <div style="text-align:center;margin-top:20px;padding:20px;background-color:<%= @color %>;">
54
+ <p style="margin:0;font-size:13px;">
55
+ <a style="color:#fff;text-decoration:none;font-size:13px;display:inline-block;" target="_blank" href="<%= @unsubscribe_url %>">
56
+ Unsubscribe
57
+ </a>
58
+ </p>
59
+ </div>
60
+
61
+ </td>
62
+ </tr>
63
+ </table>
64
+ </td>
65
+ </tr>
66
+ </table>
67
+ </body>
68
+ </html>
69
+
@@ -0,0 +1,69 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5
+ <title></title>
6
+ <style>
7
+ @media only screen and (max-width: 480px) {
8
+ #templateColumns{
9
+ width: 100% !important;
10
+ }
11
+ .templateColumnContainer{
12
+ display: block !important;
13
+ width: 100% !important;
14
+ padding: 10px !important;
15
+ }
16
+ }
17
+ </style>
18
+ </head>
19
+ <body>
20
+ <table border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable">
21
+ <tr>
22
+ <td align="center" valign="top">
23
+ <table border="0" cellpadding="20" cellspacing="0" width="800" id="emailContainer">
24
+ <tr>
25
+ <td align="center" valign="top">
26
+
27
+
28
+
29
+ <div style="text-align:center;margin-bottom:20px;padding:20px;background-color:<%= @color %>;">
30
+ <a style="display:inline-block;text-decoration:none;" href="<%= @url %>" target="_blank">
31
+ <img style="display:block;margin:0;" src="<%= @logo_url %>" alt="<%= @site.description %>" width="220" />
32
+ </a>
33
+ </div>
34
+
35
+ <div style="text-align:center;padding:20px;">
36
+ <h2>Status Changed</h2>
37
+
38
+ <% if @property %>
39
+ <%== render :partial => "caboose_rets/rets_mailer/property_row", :locals => { :p => @property, :url => @domain } %>
40
+ <div style="padding:0 10px;text-align:center;">
41
+ <p style="margin:0 0 6px 0;">
42
+ <strong>Old Status</strong>: <%= @old_status %>
43
+ </p>
44
+ <p style="margin:0;">
45
+ <strong>New Status</strong>: <%= @property.status %>
46
+ </p>
47
+ </div>
48
+ <% end %>
49
+
50
+
51
+ </div>
52
+
53
+ <div style="text-align:center;margin-top:20px;padding:20px;background-color:<%= @color %>;">
54
+ <p style="margin:0;font-size:13px;">
55
+ <a style="color:#fff;text-decoration:none;font-size:13px;display:inline-block;" target="_blank" href="<%= @unsubscribe_url %>">
56
+ Unsubscribe
57
+ </a>
58
+ </p>
59
+ </div>
60
+
61
+ </td>
62
+ </tr>
63
+ </table>
64
+ </td>
65
+ </tr>
66
+ </table>
67
+ </body>
68
+ </html>
69
+
@@ -1,6 +1,6 @@
1
1
  <div style="text-align:center;margin-bottom:20px;padding:20px;background-color:<%= @color %>;">
2
2
  <a style="display:inline-block;text-decoration:none;" href="<%= @url %>" target="_blank">
3
- <img style="display:block;" src="<%= @logo_url %>" alt="<%= @site.description %>" width="220" />
3
+ <img style="display:block;margin:0;" src="<%= @logo_url %>" alt="<%= @site.description %>" width="220" />
4
4
  </a>
5
5
  </div>
6
6
 
@@ -12,7 +12,7 @@
12
12
  </div>
13
13
 
14
14
  <div style="text-align:center;margin-top:20px;padding:20px;background-color:<%= @color %>;">
15
- <p style="margin-top:20px;font-size:13px;">
15
+ <p style="margin:0;font-size:13px;">
16
16
  <a style="color:#fff;text-decoration:none;font-size:13px;display:inline-block;" target="_blank" href="<%= @unsubscribe_url %>">
17
17
  Unsubscribe
18
18
  </a>
@@ -4,7 +4,7 @@
4
4
 
5
5
  <div class="mb-holder">
6
6
  <p><div id='user_<%= @edituser.id %>_rets_agent_mls_id' ></div></p>
7
- <% if @edituser.date_created %><p>Date Registered: <%= @edituser.date_created.in_time_zone('Central Time (US & Canada)').strftime('%B %-d, %Y') %></p><% end %>
7
+ <% if @edituser.date_created %><p>Date Registered: <%= @edituser.date_created.in_time_zone('Central Time (US & Canada)').strftime('%B %-d, %Y, %l:%M%P') %></p><% end %>
8
8
  </div>
9
9
 
10
10
  <% if @saved.count > 0 %>
@@ -15,7 +15,30 @@
15
15
  <% next if prop.nil? || prop.status != 'Active' %>
16
16
  <li>
17
17
  <a href="/properties/<%= sp.mls_number %>/details" target="_blank">MLS #<%= sp.mls_number %> - <%= prop.full_address %></a>
18
- <% if !sp.date_saved.blank? %><span> - saved on <%= sp.date_saved.in_time_zone('Central Time (US & Canada)').strftime('%B %-d, %Y') %></span><% end %>
18
+ <% if !sp.date_saved.blank? %><span> - saved on <%= sp.date_saved.in_time_zone('Central Time (US & Canada)').strftime('%B %-d, %Y, %l:%M%P') %></span><% end %>
19
+ </li>
20
+ <% end %>
21
+ </ul>
22
+ <% end %>
23
+
24
+ <% if @emails.count > 0 %>
25
+ <h3 class="sp">Emails Sent</h3>
26
+ <ul class="saved">
27
+ <% @emails.each do |em| %>
28
+ <li>
29
+ <strong><%= em.kind %></strong>
30
+ <span>- sent on <%= em.date_sent.in_time_zone('Central Time (US & Canada)').strftime('%B %-d, %Y, %l:%M%P') %></span>
31
+ <% if !em.message.blank? %>
32
+ <p><%== em.message.gsub("\n","<br />") %></p>
33
+ <% elsif em.object_kind == 'Property' && em.object_id %>
34
+ <p><a href="/properties/<%= em.object_id %>/details" target="_blank">MLS # <%= em.object_id %></a>,
35
+ <% if em.kind.include?('Price') %>
36
+ Old Price: <%= number_to_currency(em.old_value, :precision => 0) %> -> New Price: <%= number_to_currency(em.new_value, :precision => 0) %>
37
+ <% else %>
38
+ Old Status: <%= em.old_value %> -> New Status: <%= em.new_value %>
39
+ <% end %>
40
+ </p>
41
+ <% end %>
19
42
  </li>
20
43
  <% end %>
21
44
  </ul>
@@ -29,12 +52,25 @@
29
52
  margin: 30px 0 10px 0;
30
53
  }
31
54
  ul.saved {
55
+ margin: 0;
32
56
  padding-left: 0;
33
57
  list-style-type: none;
34
58
  }
35
59
  ul.saved li {
36
60
  display: block;
37
- margin-bottom: 3px;
61
+ margin-bottom: 5px;
62
+ }
63
+ ul.saved li a {
64
+ text-decoration: none;
65
+ color: #3939a7;
66
+ }
67
+ ul.saved li a:hover {
68
+ color: #59a739;
69
+ }
70
+ ul.saved li p {
71
+ margin: 3px 0 0 0;
72
+ color: #3e3e3e;
73
+ font-size: 13px;
38
74
  }
39
75
  ul.saved li a {
40
76
  text-decoration: none;
@@ -1,3 +1,3 @@
1
1
  module CabooseRets
2
- VERSION = '0.1.183'
2
+ VERSION = '0.1.184'
3
3
  end
@@ -242,6 +242,10 @@ namespace :caboose_rets do
242
242
  CabooseRets::RetsImporter.update_helper('Property', last_updated, false)
243
243
  end
244
244
 
245
+ task :send_daily_emails => :environment do
246
+ CabooseRets::Notification.delay(:queue => "rets").send_new_suggested_emails
247
+ end
248
+
245
249
  #desc "Delete old rets properties"
246
250
  #task :delete_old_properties => :environment do
247
251
  # CabooseRets::RetsImporter.delete_old_properties
@@ -275,6 +279,11 @@ namespace :caboose_rets do
275
279
  CabooseRets::RetsImporter.update_helper("OpenHouse", d, false)
276
280
  end
277
281
 
282
+ desc "update rets"
283
+ task :updater => :environment do
284
+ CabooseRets::RetsImporter.delay(:queue => "rets").update_rets
285
+ end
286
+
278
287
  desc "Updates all the listings from MLS"
279
288
  task :update_rets => :environment do
280
289
  if task_is_locked
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.1.183
4
+ version: 0.1.184
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Barry
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-27 00:00:00.000000000 Z
11
+ date: 2021-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: caboose-cms
@@ -71,6 +71,7 @@ files:
71
71
  - app/models/caboose_rets/agent_meta.rb
72
72
  - app/models/caboose_rets/log.rb
73
73
  - app/models/caboose_rets/media.rb
74
+ - app/models/caboose_rets/notification.rb
74
75
  - app/models/caboose_rets/office.rb
75
76
  - app/models/caboose_rets/office_meta.rb
76
77
  - app/models/caboose_rets/open_house.rb
@@ -107,7 +108,11 @@ files:
107
108
  - app/views/caboose_rets/properties/property_not_exists.html.erb
108
109
  - app/views/caboose_rets/properties/test_form.html.erb
109
110
  - app/views/caboose_rets/rets/admin_import_form.html.erb
111
+ - app/views/caboose_rets/rets_mailer/_property_row.html.erb
112
+ - app/views/caboose_rets/rets_mailer/daily_report.html.erb
110
113
  - app/views/caboose_rets/rets_mailer/new_user.html.erb
114
+ - app/views/caboose_rets/rets_mailer/property_price_change.html.erb
115
+ - app/views/caboose_rets/rets_mailer/property_status_change.html.erb
111
116
  - app/views/caboose_rets/rets_mailer/user_welcome.html.erb
112
117
  - app/views/caboose_rets/saved_properties/index.html.erb
113
118
  - app/views/caboose_rets/saved_properties/rets_info.html.erb