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 +4 -4
- 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 +15 -0
- data/app/models/caboose_rets/rets_importer.rb +19 -183
- data/app/models/caboose_rets/schema.rb +12 -0
- data/app/views/caboose_rets/rets_mailer/_property_row.html.erb +31 -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: 84ef101eafb83b5891a32f9557f355e5f46de43e3d1e544aad19e5a533e78b6e
|
4
|
+
data.tar.gz: 1ddefc2dbff138dcb82eb3e4c879f9b19956726d2dd20ca134ec7106a45ce99e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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').
|
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 = "
|
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
|
-
|
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
|
-
|
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
|
-
|
591
|
-
|
592
|
-
|
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 -
|
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
|
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.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-
|
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
|