caboose-rets 0.1.183 → 0.1.187
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 +4 -4
- data/app/controllers/caboose_rets/properties_controller.rb +11 -0
- data/app/controllers/caboose_rets/saved_properties_controller.rb +2 -1
- data/app/mailers/caboose_rets/rets_mailer.rb +72 -0
- data/app/models/caboose_rets/notification.rb +206 -0
- data/app/models/caboose_rets/property.rb +21 -0
- data/app/models/caboose_rets/rets_importer.rb +19 -184
- data/app/models/caboose_rets/schema.rb +12 -0
- data/app/views/caboose_rets/rets_mailer/_property_row.html.erb +28 -0
- data/app/views/caboose_rets/rets_mailer/daily_report.html.erb +76 -0
- data/app/views/caboose_rets/rets_mailer/property_price_change.html.erb +69 -0
- data/app/views/caboose_rets/rets_mailer/property_status_change.html.erb +69 -0
- data/app/views/caboose_rets/rets_mailer/user_welcome.html.erb +2 -2
- data/app/views/caboose_rets/saved_properties/rets_info.html.erb +39 -3
- data/lib/caboose_rets/version.rb +1 -1
- data/lib/tasks/caboose_rets.rake +9 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 936a3227a63e02f4e6fdecdedd4113d43efbbbff3bcc514949fdc1c172116488
|
4
|
+
data.tar.gz: 7d6b834190be3bc8639ee9bb98181a2dffcb14877972ff04fee70d2ea1b94968
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d261fa947e2ca6965d3c8a373f29b6285c8e3cdb5e6dc415dcf2e9e68120f0065d6e27906a39299343f2db7ebf045ddf3e0db9ac18110fe10e993ba15fa95d6
|
7
|
+
data.tar.gz: 9e59c90155e5b19d4c2ee691cc7a76eb950eaa9b8c407736aa4d380350c40321c6874e5b3b86b8007f0e08e28bee417daaa2b014e2d677a600f312df9e3b83d8
|
@@ -217,6 +217,17 @@ module CabooseRets
|
|
217
217
|
render :json => resp
|
218
218
|
end
|
219
219
|
|
220
|
+
# @route GET /api/rets-properties/:mls/photo
|
221
|
+
def dynamic_photo_url
|
222
|
+
render :json => false and return if !@site || !@site.use_rets
|
223
|
+
p = Property.where(:mls_number => params[:mls]).first
|
224
|
+
if p
|
225
|
+
redirect_to p.featured_photo_url, :status => 307 and return
|
226
|
+
else
|
227
|
+
redirect_to "https://cabooseit.s3.amazonaws.com/assets/pmre/house.png", :status => 307 and return
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
220
231
|
# @route GET /admin/properties/:id/refresh
|
221
232
|
def admin_refresh
|
222
233
|
return unless (user_is_allowed_to 'edit', 'rets_properties')
|
@@ -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').
|
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 && user.site && user.site.use_rets
|
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 && user.site && user.site.use_rets
|
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,13 +24,21 @@ 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
|
|
36
|
+
def dynamic_photo_url(site)
|
37
|
+
domain = site.primary_domain.domain
|
38
|
+
return "http://dev.pmre.com:3000/api/rets-properties/#{self.mls_number}/photo.jpg" if Rails.env.development?
|
39
|
+
return "https://#{domain}/api/rets-properties/#{self.mls_number}/photo.jpg"
|
40
|
+
end
|
41
|
+
|
34
42
|
def agent
|
35
43
|
CabooseRets::Agent.where(:mls_id => self.list_agent_mls_id).first
|
36
44
|
end
|
@@ -55,6 +63,10 @@ class CabooseRets::Property <ActiveRecord::Base
|
|
55
63
|
end
|
56
64
|
|
57
65
|
def parse(data)
|
66
|
+
|
67
|
+
old_price = self.list_price
|
68
|
+
old_status = self.status
|
69
|
+
|
58
70
|
# puts(data.to_s)
|
59
71
|
# self.access = nil
|
60
72
|
self.acreage = data['LotSizeAcres'].blank? ? nil : data['LotSizeAcres'].to_f
|
@@ -249,5 +261,14 @@ class CabooseRets::Property <ActiveRecord::Base
|
|
249
261
|
self.zoning = data['Zoning']
|
250
262
|
# self.zoning_northport = data['ZoningNorthPort']
|
251
263
|
# self.zoning_tusc = data['ZoningTusc']
|
264
|
+
|
265
|
+
|
266
|
+
if !old_status.blank? && old_status != self.status # status was changed
|
267
|
+
CabooseRets::Notification.delay(:queue => "rets").property_status_changed(self, old_status)
|
268
|
+
elsif !old_price.blank? && old_price != self.list_price && self.status == 'Active' # price was changed
|
269
|
+
CabooseRets::Notification.delay(:queue => "rets").property_price_changed(self, old_price)
|
270
|
+
end
|
271
|
+
|
272
|
+
|
252
273
|
end
|
253
274
|
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 = "
|
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 = {
|
@@ -186,22 +185,10 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
186
185
|
|
187
186
|
end
|
188
187
|
|
189
|
-
|
190
188
|
#=============================================================================
|
191
189
|
# Single model import methods (called from a worker dyno)
|
192
190
|
#=============================================================================
|
193
191
|
|
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
192
|
def self.import_properties(mls_id, save_images = true)
|
206
193
|
si = save_images ? 'saving images' : 'not saving images'
|
207
194
|
self.log3('Property',mls_id,"Importing Property #{mls_id} and #{si}...")
|
@@ -209,12 +196,12 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
209
196
|
self.import('Property', "(ListingId=#{mls_id})")
|
210
197
|
p = CabooseRets::Property.where(:mls_number => mls_id.to_s).first
|
211
198
|
if p != nil && p.status == 'Active'
|
212
|
-
self.download_property_images(p) if save_images == true
|
199
|
+
self.download_property_images(p) if save_images == true && Rails.env.production?
|
213
200
|
if p.latitude.blank? || p.latitude == '0.0' || p.longitude.blank? || p.longitude == '0.0'
|
214
201
|
self.update_coords(p)
|
215
202
|
end
|
216
203
|
else
|
217
|
-
self.log3(nil,nil,"No Property associated with #{mls_id}")
|
204
|
+
self.log3(nil,nil,"No Active Property associated with #{mls_id}, not downloading images")
|
218
205
|
end
|
219
206
|
end
|
220
207
|
|
@@ -265,43 +252,8 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
265
252
|
# Images go here
|
266
253
|
#=============================================================================
|
267
254
|
|
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
255
|
def self.download_property_images(p)
|
256
|
+
return if Rails.env.development?
|
305
257
|
self.log3('Property',p.mls_number,"Downloading images for #{p.mls_number}...")
|
306
258
|
ids_to_keep = []
|
307
259
|
begin
|
@@ -369,93 +321,21 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
369
321
|
end
|
370
322
|
end
|
371
323
|
|
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
324
|
end
|
425
325
|
|
426
326
|
def self.download_missing_images
|
427
327
|
self.log3("Property",nil,"Downloading all missing images...")
|
428
|
-
CabooseRets::Property.where("photo_count = ? OR photo_count is null", '').all.each do |p|
|
328
|
+
CabooseRets::Property.where("photo_count = ? OR photo_count is null", '').where(:status => "Active").all.each do |p|
|
429
329
|
self.delay(:priority => 10, :queue => 'rets').import_properties(p.mls_number, true)
|
430
330
|
end
|
431
331
|
end
|
432
332
|
|
433
333
|
def self.download_agent_image(agent)
|
434
|
-
|
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
|
334
|
+
|
445
335
|
end
|
446
336
|
|
447
337
|
def self.download_office_image(office)
|
448
|
-
|
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
|
338
|
+
|
459
339
|
end
|
460
340
|
|
461
341
|
#=============================================================================
|
@@ -517,6 +397,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
517
397
|
def self.purge_open_houses() self.delay(:priority => 10, :queue => 'rets').purge_helper('OpenHouse', '2012-01-01') end
|
518
398
|
|
519
399
|
|
400
|
+
# Adds/removes records in the database
|
520
401
|
def self.purge_helper(class_type, date_modified)
|
521
402
|
m = self.meta(class_type)
|
522
403
|
self.log(m.search_type)
|
@@ -573,12 +454,12 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
573
454
|
ids_to_remove = local_ids - ids
|
574
455
|
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
456
|
|
576
|
-
# Delete all RetsMedia and CabooseMedia for the deleted property listings
|
457
|
+
# Delete all RetsMedia and CabooseMedia for the deleted property listings (except keep the first image)
|
577
458
|
if class_type == 'Property' && ids_to_remove && ids_to_remove.count > 0
|
578
459
|
self.log3(class_type,nil,"Deleting Media objects that shouldn't be there...")
|
579
460
|
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|
|
461
|
+
if muis && muis.count > 0 && Rails.env.production?
|
462
|
+
CabooseRets::Media.where("media_mui in (?)", muis).where("media_order != ?", 1).each do |med|
|
582
463
|
self.log3("Media",med.id,"Deleting old RetsMedia #{med.id} and CabooseMedia #{med.media_id}...")
|
583
464
|
m = Caboose::Media.where(:id => med.media_id).where("name ILIKE ?","rets_media%").first
|
584
465
|
m.destroy if m
|
@@ -587,9 +468,11 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
587
468
|
end
|
588
469
|
end
|
589
470
|
|
590
|
-
|
591
|
-
|
592
|
-
|
471
|
+
if class_type != 'Property' # keep all properties in the DB
|
472
|
+
self.log3(class_type,nil,"Deleting #{class_type} records in the local database that shouldn't be there...")
|
473
|
+
query = ["delete from #{t} where #{k} in (?)", ids_to_remove]
|
474
|
+
ActiveRecord::Base.connection.execute(ActiveRecord::Base.send(:sanitize_sql_array, query))
|
475
|
+
end
|
593
476
|
|
594
477
|
# Find any ids in the remote database that should be in the local database
|
595
478
|
self.log3(class_type,nil,"Finding #{class_type} records in the remote database that should be in the local database...")
|
@@ -612,54 +495,6 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
612
495
|
end
|
613
496
|
end
|
614
497
|
|
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
498
|
#=============================================================================
|
664
499
|
# Logging
|
665
500
|
#=============================================================================
|
@@ -704,7 +539,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
704
539
|
overlap = 1.week
|
705
540
|
end
|
706
541
|
self.update_after((self.last_updated - overlap), false)
|
707
|
-
self.download_missing_images
|
542
|
+
self.download_missing_images if Rails.env.production?
|
708
543
|
self.log3(nil,nil,"Saving the timestamp for when we updated to #{task_started.to_s}...")
|
709
544
|
self.save_last_updated(task_started)
|
710
545
|
self.log2("Unlocking the task...")
|
@@ -725,7 +560,7 @@ class CabooseRets::RetsImporter # < ActiveRecord::Base
|
|
725
560
|
end
|
726
561
|
|
727
562
|
# Delete RETS logs over 7 days old
|
728
|
-
dt = DateTime.now -
|
563
|
+
dt = DateTime.now - 5.days
|
729
564
|
sql = "delete from rets_logs where timestamp < '#{dt}';"
|
730
565
|
ActiveRecord::Base.connection.select_all(sql)
|
731
566
|
|
@@ -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,28 @@
|
|
1
|
+
<table border="0" cellpadding="0" cellspacing="0" width="100%" 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
|
+
<img style="display:block;max-width:200px;height:auto;" width="200" alt="MLS # <%= p.mls_number %>" src="<%= p.dynamic_photo_url(@site) %>" />
|
6
|
+
</a>
|
7
|
+
</td>
|
8
|
+
<td align="left" valign="top" width="37.5%" class="templateColumnContainer" style="width:37.5%;padding:5px 5px 5px 10px;">
|
9
|
+
<p style="margin:0 0 5px 0;font-size:14px;line-height:16px;"><strong>MLS#: <%= p.mls_number %></strong></p>
|
10
|
+
<address style="margin:0 0 5px 0;font-size:15px;line-height:17px;"><%== p.full_address_city %></address>
|
11
|
+
<p style="margin:0 0 5px 0;font-size:15px;line-height:17px;">
|
12
|
+
<% if !p.subdivision.blank? %><span><%= p.subdivision.titleize %></span> | <% end %>
|
13
|
+
<% if !p.city.blank? && p.city.upcase != "NONE" %><span><%= p.city.titleize %></span><% end %>
|
14
|
+
</p>
|
15
|
+
</td>
|
16
|
+
<td align="left" valign="top" width="37.5%" class="templateColumnContainer" style="width:37.5%;padding:5px 0 5px 10px;">
|
17
|
+
<p style="margin:0 0 5px 0;font-size:16px;line-height:18px;"><strong><%= number_to_currency(p.list_price, :precision => 0) %></strong></p>
|
18
|
+
<p style="margin:0 0 5px 0;font-size:15px;line-height:17px;">
|
19
|
+
<% if !p.beds_total.blank? %><span><strong><%= p.beds_total %></strong> beds</span><br /><% end %>
|
20
|
+
<% if !p.baths_full.blank? %><span><strong><%= p.baths_full %> <% if p.baths_half == 1 %>½ <% end %></strong>baths</span><br /><% end %>
|
21
|
+
<% if !p.sqft_total.blank? %><span><strong><%= number_with_delimiter(p.sqft_total.to_i, :delimiter => ',') %></strong> sqft</span><% end %>
|
22
|
+
</p>
|
23
|
+
<% if !p.original_entry_timestamp.blank? %>
|
24
|
+
<p style="margin:0;font-size:13px;line-height:15px;">Listed <%= time_ago_in_words(p.original_entry_timestamp) %> ago</p>
|
25
|
+
<% end %>
|
26
|
+
</td>
|
27
|
+
</tr>
|
28
|
+
</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="100%" 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;max-width:800px;margin:0 auto;">
|
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="100%" 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;max-width:800px;margin:0 auto;">
|
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="100%" 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;max-width:800px;margin:0 auto;">
|
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
|
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:
|
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;
|
data/lib/caboose_rets/version.rb
CHANGED
data/lib/tasks/caboose_rets.rake
CHANGED
@@ -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.
|
4
|
+
version: 0.1.187
|
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-
|
11
|
+
date: 2021-08-12 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
|