mls 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/mls +17 -0
- data/lib/mls.rb +3 -1
- data/lib/mls/cli.rb +48 -0
- data/lib/mls/cli/documents.rb +71 -0
- data/lib/mls/cli/storage.rb +1 -0
- data/lib/mls/cli/storage/s3.rb +99 -0
- data/lib/mls/{account.rb → models/account.rb} +27 -7
- data/lib/mls/{accounts_region.rb → models/accounts_region.rb} +0 -0
- data/lib/mls/models/action.rb +44 -0
- data/lib/mls/{address.rb → models/address.rb} +0 -0
- data/lib/mls/{api_key.rb → models/api_key.rb} +0 -0
- data/lib/mls/{coworking_space.rb → models/coworking_space.rb} +0 -1
- data/lib/mls/{credit_card.rb → models/credit_card.rb} +0 -0
- data/lib/mls/{datum.rb → models/datum.rb} +0 -0
- data/lib/mls/{document.rb → models/document.rb} +0 -0
- data/lib/mls/{email.rb → models/email.rb} +0 -0
- data/lib/mls/{email_address.rb → models/email_address.rb} +0 -0
- data/lib/mls/models/email_digest.rb +13 -0
- data/lib/mls/{event.rb → models/event.rb} +0 -0
- data/lib/mls/{flyer.rb → models/flyer.rb} +0 -0
- data/lib/mls/{geometry.rb → models/geometry.rb} +0 -0
- data/lib/mls/{image_ordering.rb → models/image_ordering.rb} +0 -0
- data/lib/mls/{impression_count.rb → models/impression_count.rb} +0 -0
- data/lib/mls/{inquiry.rb → models/inquiry.rb} +16 -1
- data/lib/mls/{invoice.rb → models/invoice.rb} +1 -1
- data/lib/mls/models/lead.rb +26 -0
- data/lib/mls/{listing.rb → models/listing.rb} +20 -4
- data/lib/mls/{locality.rb → models/locality.rb} +0 -0
- data/lib/mls/{metadatum.rb → models/metadatum.rb} +0 -0
- data/lib/mls/{mistake.rb → models/mistake.rb} +0 -0
- data/lib/mls/{organization.rb → models/organization.rb} +0 -0
- data/lib/mls/{ownership.rb → models/ownership.rb} +0 -0
- data/lib/mls/{phone.rb → models/phone.rb} +0 -0
- data/lib/mls/{property.rb → models/property.rb} +31 -3
- data/lib/mls/{recommendation.rb → models/recommendation.rb} +0 -0
- data/lib/mls/{reference.rb → models/reference.rb} +0 -0
- data/lib/mls/{region.rb → models/region.rb} +8 -2
- data/lib/mls/models/search.rb +63 -0
- data/lib/mls/models/service.rb +11 -0
- data/lib/mls/{session.rb → models/session.rb} +0 -0
- data/lib/mls/models/site.rb +26 -0
- data/lib/mls/{slug.rb → models/slug.rb} +0 -0
- data/lib/mls/{source.rb → models/source.rb} +0 -0
- data/lib/mls/{space.rb → models/space.rb} +0 -0
- data/lib/mls/{stat.rb → models/stat.rb} +0 -0
- data/lib/mls/models/subscription.rb +19 -0
- data/lib/mls/models/suggestion.rb +13 -0
- data/lib/mls/{task.rb → models/task.rb} +0 -0
- data/lib/mls/{team.rb → models/team.rb} +0 -0
- data/lib/mls/models/tim_alert.rb +7 -0
- data/lib/mls/{time_log.rb → models/time_log.rb} +0 -0
- data/lib/mls/{use.rb → models/use.rb} +0 -0
- data/lib/mls/{vendor.rb → models/vendor.rb} +0 -0
- data/lib/mls/{view.rb → models/view.rb} +0 -0
- data/lib/mls/{webpage.rb → models/webpage.rb} +0 -0
- data/lib/mls/rack/proxy.rb +78 -0
- data/lib/mls/railtie.rb +32 -0
- data/mls.gemspec +1 -1
- metadata +61 -49
- data/lib/mls/action.rb +0 -18
- data/lib/mls/email_digest.rb +0 -10
- data/lib/mls/lead.rb +0 -6
- data/lib/mls/membership.rb +0 -27
- data/lib/mls/subscription.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '05855a1a8a8ff7514aa0d09798c336972c6443cc'
|
4
|
+
data.tar.gz: 689bc19414f3f6516d74bb8f8721d6019fb86060
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e675d1684d26d1fc2a5c64fe995bce74f185090a161844091bc24b5bfc7d6f36d723d2a6f57700ee41589dedb58d77044ab29a752ed75c3783f714fa2bdc827b
|
7
|
+
data.tar.gz: a94d1a6219a065cbc0c436e167f06a333c90662aec2160d5cf62e3a4dd1bed96100d2296e364d1ce71c9fd1b9cb6488aaaced1e66cdd0f9e60bf683534fad5ae
|
data/bin/mls
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.expand_path('../../lib/mls/cli', __FILE__)
|
3
|
+
|
4
|
+
case ARGV.shift.downcase.strip
|
5
|
+
when "documents:backup"
|
6
|
+
MLS::CLI.parse_args(ARGV).inspect
|
7
|
+
directory = ARGV.shift
|
8
|
+
|
9
|
+
if directory.nil? || !File.directory?(directory)
|
10
|
+
puts "Usage: mls documents:backup dir [options...]"
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
MLS::CLI::Documents.backup(directory)
|
15
|
+
else
|
16
|
+
puts "Usage: mls documents:backup dir [options...]"
|
17
|
+
end
|
data/lib/mls.rb
CHANGED
data/lib/mls/cli.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path('../../mls', __FILE__)
|
2
|
+
require 'uri'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
module MLS::CLI
|
6
|
+
|
7
|
+
def self.options
|
8
|
+
if !class_variable_defined?(:@@options)
|
9
|
+
@@options = {}
|
10
|
+
end
|
11
|
+
@@options
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.parse_args(args)
|
15
|
+
OptionParser.new do |opts|
|
16
|
+
opts.on("-aURL", "--auth=URL", "URL Credentials for MLS, S3 or B2") do |arg|
|
17
|
+
url = URI.parse(arg)
|
18
|
+
case url.scheme
|
19
|
+
when 's3' # ACCESS_KEY:SECRET_KEY@BUCKET[/PREFIX][?parition=4]
|
20
|
+
MLS::CLI.options[:s3] = {
|
21
|
+
access_key_id: URI.unescape(url.user),
|
22
|
+
secret_access_key: URI.unescape(url.password),
|
23
|
+
bucket: URI.unescape(url.host)
|
24
|
+
}
|
25
|
+
MLS::CLI.options[:s3][:prefix] = url.path if url.path && !url.path.empty?
|
26
|
+
url.query.split('&').each do |qp|
|
27
|
+
key, value = qp.split('=').map { |d| URI.unescape(d) }
|
28
|
+
case key
|
29
|
+
when 'partition'
|
30
|
+
MLS::CLI.options[:s3][:partition] = true
|
31
|
+
MLS::CLI.options[:s3][:partition_depth] = value.to_i
|
32
|
+
end
|
33
|
+
end
|
34
|
+
when 'b2'
|
35
|
+
|
36
|
+
when 'mls'
|
37
|
+
arg = arg.sub('mls://', 'https://')
|
38
|
+
MLS::CLI.options[:mls] = arg
|
39
|
+
MLS::Model.establish_connection(adapter: 'sunstone', url: arg)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end.parse!(args)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
require File.expand_path('../cli/storage', __FILE__)
|
48
|
+
require File.expand_path('../cli/documents', __FILE__)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'digest'
|
3
|
+
|
4
|
+
module MLS::CLI::Documents
|
5
|
+
|
6
|
+
def self.partition(value, depth: 5)
|
7
|
+
split = value.scan(/.{1,4}/)
|
8
|
+
split.shift(depth).join("/") + split.join("")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.calculate_digest(file)
|
12
|
+
md5_digest = Digest::MD5.new
|
13
|
+
sha1_digest = Digest::SHA1.new
|
14
|
+
sha256_digest = Digest::SHA256.new
|
15
|
+
|
16
|
+
buf = ""
|
17
|
+
file.rewind
|
18
|
+
while file.read(16384, buf)
|
19
|
+
md5_digest << buf
|
20
|
+
sha1_digest << buf
|
21
|
+
sha256_digest << buf
|
22
|
+
end
|
23
|
+
|
24
|
+
{
|
25
|
+
md5: md5_digest.hexdigest,
|
26
|
+
sha1: sha1_digest.hexdigest,
|
27
|
+
sha256: sha256_digest.hexdigest
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.backup(dir)
|
32
|
+
last_sync_file = File.join(dir, '.last_sync')
|
33
|
+
|
34
|
+
query = if File.exist?(last_sync_file)
|
35
|
+
from_timestamp = Time.iso8601(File.read(last_sync_file))
|
36
|
+
Document.filter(created_at: {gte: from_timestamp})
|
37
|
+
else
|
38
|
+
Document.all
|
39
|
+
end
|
40
|
+
|
41
|
+
query.find_each do |document|
|
42
|
+
if document.sha256 && File.exists?(File.join(dir, partition(document.sha256)))
|
43
|
+
puts "Downloaded #{document.id}"
|
44
|
+
next
|
45
|
+
end
|
46
|
+
|
47
|
+
if document.provider.nil? || document.provider.include?('s3/hash_key')
|
48
|
+
storage_engine = MLS::CLI::Storage::S3.new(MLS::CLI.options[:s3])
|
49
|
+
key = 'hash_key'
|
50
|
+
else
|
51
|
+
raise 'unkown storage engine'
|
52
|
+
end
|
53
|
+
|
54
|
+
puts "Downloading #{document.id}"
|
55
|
+
storage_engine.copy_to_tempfile(document.send(key)) do |file|
|
56
|
+
digests = calculate_digest(file)
|
57
|
+
|
58
|
+
raise 'MD5 does not match' if digests[:md5] != document.md5
|
59
|
+
document.update!(digests.merge({provider: ['s3/hash_key']}))
|
60
|
+
|
61
|
+
FileUtils.mkdir_p(File.dirname(File.join(dir, partition(document.sha256))))
|
62
|
+
FileUtils.mv(file.path, File.join(dir, partition(document.sha256)), verbose: true)
|
63
|
+
end
|
64
|
+
|
65
|
+
File.write(last_sync_file, document.created_at.iso8601(6))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.expand_path('../storage/s3', __FILE__)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'aws-sdk-s3'
|
2
|
+
|
3
|
+
module MLS::CLI::Storage
|
4
|
+
class S3
|
5
|
+
|
6
|
+
def initialize(configs = {})
|
7
|
+
@configs = configs
|
8
|
+
@configs[:region] ||= 'us-east-1'
|
9
|
+
@configs[:prefix] ||= ""
|
10
|
+
|
11
|
+
@client = Aws::S3::Client.new({
|
12
|
+
access_key_id: configs[:access_key_id],
|
13
|
+
secret_access_key: configs[:secret_access_key],
|
14
|
+
region: configs[:region]
|
15
|
+
})
|
16
|
+
end
|
17
|
+
|
18
|
+
def object_for(key)
|
19
|
+
Aws::S3::Object.new(@configs[:bucket], key, client: @client)
|
20
|
+
end
|
21
|
+
|
22
|
+
def local?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def url(key)
|
27
|
+
[host, destination(key)].join('/')
|
28
|
+
end
|
29
|
+
|
30
|
+
def host
|
31
|
+
h = @configs[:bucket_host_alias] || "https://s3.amazonaws.com/#{@configs[:bucket]}"
|
32
|
+
h.delete_suffix('/')
|
33
|
+
end
|
34
|
+
|
35
|
+
def destination(key)
|
36
|
+
"#{@configs[:prefix]}#{partition(key)}".gsub(/^\//, '')#delete_prefix('/')
|
37
|
+
end
|
38
|
+
|
39
|
+
def exists?(key)
|
40
|
+
object_for(destination(key)).exists?
|
41
|
+
end
|
42
|
+
|
43
|
+
# def write(key, file, meta_info)
|
44
|
+
# file = file.tempfile if file.is_a?(ActionDispatch::Http::UploadedFile)
|
45
|
+
#
|
46
|
+
# object_for(destination(key)).upload_file(file, {
|
47
|
+
# :acl => 'public-read',
|
48
|
+
# :content_disposition => "inline; filename=\"#{meta_info[:filename]}\"",
|
49
|
+
# :content_type => meta_info[:content_type]
|
50
|
+
# })
|
51
|
+
# end
|
52
|
+
|
53
|
+
def read(key, &block)
|
54
|
+
object_for(destination(key)).get()
|
55
|
+
end
|
56
|
+
|
57
|
+
def cp(key, path)
|
58
|
+
object_for(destination(key)).get({ response_target: path })
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete(key)
|
63
|
+
object_for(destination(key)).delete
|
64
|
+
end
|
65
|
+
|
66
|
+
def copy_to_tempfile(key)
|
67
|
+
tmpfile = Tempfile.new([File.basename(key), File.extname(key)], binmode: true)
|
68
|
+
cp(key, tmpfile.path)
|
69
|
+
if block_given?
|
70
|
+
begin
|
71
|
+
yield(tmpfile)
|
72
|
+
ensure
|
73
|
+
tmpfile.close!
|
74
|
+
end
|
75
|
+
else
|
76
|
+
tmpfile
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def partition(value)
|
81
|
+
return value unless @configs[:partition]
|
82
|
+
split = value.scan(/.{1,4}/)
|
83
|
+
split.shift(@configs[:partition_depth] || 3).join("/") + split.join("")
|
84
|
+
end
|
85
|
+
|
86
|
+
def md5(key)
|
87
|
+
object_for(destination(key)).etag
|
88
|
+
end
|
89
|
+
|
90
|
+
def last_modified(key)
|
91
|
+
object_for(destination(key)).last_modified
|
92
|
+
end
|
93
|
+
|
94
|
+
def mime_type(key)
|
95
|
+
object_for(destination(key)).content_type
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -4,17 +4,23 @@ class Account < MLS::Model
|
|
4
4
|
include MLS::Avatar
|
5
5
|
|
6
6
|
belongs_to :organization
|
7
|
-
belongs_to :
|
8
|
-
|
7
|
+
belongs_to :cobroke_manager, class_name: "Account"
|
8
|
+
|
9
|
+
has_and_belongs_to_many :subscriptions
|
9
10
|
has_many :tasks
|
10
11
|
has_many :sources
|
11
12
|
has_many :ownerships, :inverse_of => :account, :dependent => :delete_all
|
12
13
|
has_many :assets, through: :ownerships
|
13
14
|
has_many :coworking_spaces, through: :ownerships, source: :asset, source_type: 'CoworkingSpace'
|
14
15
|
has_many :listings, through: :ownerships, source: :asset, source_type: 'Listing', inverse_of: :accounts
|
16
|
+
has_many :sites, through: :ownerships, source: :asset, source_type: 'Site', inverse_of: :accounts
|
15
17
|
has_many :email_digests
|
16
|
-
has_many :
|
17
|
-
has_many :
|
18
|
+
has_many :services, as: :subject
|
19
|
+
has_many :tim_alerts
|
20
|
+
has_many :references, as: :subject
|
21
|
+
|
22
|
+
has_many :searches
|
23
|
+
has_many :suggestions, foreign_key: "suggested_by_id"
|
18
24
|
|
19
25
|
has_many :credit_cards
|
20
26
|
|
@@ -28,6 +34,10 @@ class Account < MLS::Model
|
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
37
|
+
|
38
|
+
def deals
|
39
|
+
Search.filter([{manager_id: self.id}, "OR", {broker_id: self.id}])
|
40
|
+
end
|
31
41
|
|
32
42
|
has_many :phones do
|
33
43
|
|
@@ -66,15 +76,19 @@ class Account < MLS::Model
|
|
66
76
|
end
|
67
77
|
|
68
78
|
def tim_alerts?
|
69
|
-
|
79
|
+
subscriptions.map{|x| x.services.filter(status: "active", type: "tim_alerts").count}.sum > 0
|
70
80
|
end
|
71
81
|
|
72
82
|
def unlimited?
|
73
|
-
|
83
|
+
subscriptions.map{|x| x.services.filter(status: "active", type: "unlimited").count}.sum > 0
|
84
|
+
end
|
85
|
+
|
86
|
+
def referral?
|
87
|
+
subscriptions.map{|x| x.services.filter(status: "active", type: "referral").count}.sum > 0
|
74
88
|
end
|
75
89
|
|
76
90
|
def paying?
|
77
|
-
|
91
|
+
subscriptions.map{|x| x.services.filter(status: "active").count}.sum > 0
|
78
92
|
end
|
79
93
|
|
80
94
|
def password_required?
|
@@ -153,6 +167,12 @@ class Account < MLS::Model
|
|
153
167
|
req.body = {url: url}.to_json
|
154
168
|
Account.connection.instance_variable_get(:@connection).send_request(req)
|
155
169
|
end
|
170
|
+
|
171
|
+
def set_confirmation_token
|
172
|
+
req = Net::HTTP::Get.new("/accounts/#{self.id}/confirm")
|
173
|
+
response = Account.connection.instance_variable_get(:@connection).send_request(req)
|
174
|
+
self.confirmation_token = response.body
|
175
|
+
end
|
156
176
|
|
157
177
|
|
158
178
|
end
|
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Action < MLS::Model
|
2
|
+
self.inheritance_column = nil
|
3
|
+
attr_accessor :account_id
|
4
|
+
|
5
|
+
belongs_to :event
|
6
|
+
belongs_to :subject, :polymorphic => true
|
7
|
+
|
8
|
+
has_many :mistakes
|
9
|
+
has_many :metadata, foreign_key: :event_id, primary_key: :event_id
|
10
|
+
|
11
|
+
def self.by_performer(filter)
|
12
|
+
req = Net::HTTP::Get.new("/actions/by_performer")
|
13
|
+
req.body = {
|
14
|
+
where: filter
|
15
|
+
}.to_json
|
16
|
+
JSON.parse(connection.instance_variable_get(:@connection).send_request(req).body)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.squash(attributes)
|
20
|
+
squashed_actions = []
|
21
|
+
where(nil).each do |action|
|
22
|
+
action.account_id = action.metadata.where(key: 'performed_by_id').first&.value
|
23
|
+
|
24
|
+
action.diff = action.diff.slice(*attributes) if attributes
|
25
|
+
if squashed_actions.last &&
|
26
|
+
action.account_id == squashed_actions.last.account_id &&
|
27
|
+
action.timestamp + 15.minutes > squashed_actions.last.timestamp
|
28
|
+
|
29
|
+
action.diff.each do |key, value|
|
30
|
+
next if value[0] == value[1] # filter sometimes logs even if the same
|
31
|
+
if squashed_actions.last.diff[key]
|
32
|
+
squashed_actions.last.diff[key][0] = value[0]
|
33
|
+
else
|
34
|
+
squashed_actions.last.diff[key] = value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
squashed_actions << action
|
39
|
+
end
|
40
|
+
end
|
41
|
+
squashed_actions
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class EmailDigest < MLS::Model
|
2
|
+
|
3
|
+
belongs_to :search
|
4
|
+
belongs_to :account
|
5
|
+
accepts_nested_attributes_for :account
|
6
|
+
|
7
|
+
def filter
|
8
|
+
filter_to_read = read_attribute(:filter)
|
9
|
+
filter_to_read = search.filter if filter_to_read&.empty? && search
|
10
|
+
JSON.parse (filter_to_read || {}).to_json, object_class: OpenStruct
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class Inquiry < MLS::Model
|
2
|
+
|
3
|
+
TERMS = %w(<1 1-2 3-5 5+ flexible)
|
2
4
|
|
3
5
|
has_many :emails
|
4
|
-
has_many :leads
|
5
6
|
belongs_to :subject, polymorphic: true
|
6
7
|
belongs_to :account
|
7
8
|
|
@@ -10,6 +11,20 @@ class Inquiry < MLS::Model
|
|
10
11
|
def property
|
11
12
|
subject.is_a? MLS::Model::Listing ? subject.property : subject
|
12
13
|
end
|
14
|
+
|
15
|
+
def term_units(value=nil)
|
16
|
+
value ||= self.term
|
17
|
+
case value
|
18
|
+
when "<1"
|
19
|
+
"year"
|
20
|
+
when "flexible"
|
21
|
+
""
|
22
|
+
when nil
|
23
|
+
""
|
24
|
+
else
|
25
|
+
"years"
|
26
|
+
end
|
27
|
+
end
|
13
28
|
|
14
29
|
def account_attributes=(account_attrs)
|
15
30
|
account_attrs = account_attrs&.with_indifferent_access
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Lead < MLS::Model
|
2
|
+
|
3
|
+
STATUSES = %w(delivered connected touring proposals leases closed lost)
|
4
|
+
|
5
|
+
has_many :inquiries
|
6
|
+
has_many :tim_alerts
|
7
|
+
|
8
|
+
def regions
|
9
|
+
Region.where(id: region_ids)
|
10
|
+
end
|
11
|
+
|
12
|
+
def term_units(value=nil)
|
13
|
+
value ||= self.term
|
14
|
+
case value
|
15
|
+
when "<1"
|
16
|
+
"year"
|
17
|
+
when "flexible"
|
18
|
+
""
|
19
|
+
when nil
|
20
|
+
""
|
21
|
+
else
|
22
|
+
"years"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -37,6 +37,10 @@ class Listing < MLS::Model
|
|
37
37
|
|
38
38
|
accepts_nested_attributes_for :uses, :ownerships, :image_orderings
|
39
39
|
|
40
|
+
def is_elite?
|
41
|
+
((property.elite_account_ids || []) & accounts.map(&:id)).length > 0
|
42
|
+
end
|
43
|
+
|
40
44
|
def premium_property?
|
41
45
|
Subscription.filter(started_at: true, ends_at: false, type: "premium", subject_type: "Property", subject_id: self.property_id).count > 0
|
42
46
|
end
|
@@ -49,11 +53,11 @@ class Listing < MLS::Model
|
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
52
|
-
def
|
56
|
+
def lead_contacts
|
53
57
|
if ownerships.loaded?
|
54
|
-
@
|
58
|
+
@lead_contacts ||= ownerships.select{|o| o.lead}.map(&:account)
|
55
59
|
else
|
56
|
-
@
|
60
|
+
@lead_contacts ||= ownerships.eager_load(:account).filter(:lead => true).map(&:account)
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
@@ -147,7 +151,7 @@ class Listing < MLS::Model
|
|
147
151
|
def name
|
148
152
|
return "New Listing" if !self.id
|
149
153
|
name = ""
|
150
|
-
if self.
|
154
|
+
if self.unit_type == "building"
|
151
155
|
name += "Entire Building"
|
152
156
|
else
|
153
157
|
name = "Unit #{self.unit}" if self.unit.present?
|
@@ -158,4 +162,16 @@ class Listing < MLS::Model
|
|
158
162
|
name = "Space" if name.blank?
|
159
163
|
name
|
160
164
|
end
|
165
|
+
|
166
|
+
def status
|
167
|
+
if self.leased_at
|
168
|
+
"Leased"
|
169
|
+
elsif self.archived
|
170
|
+
"Deleted"
|
171
|
+
elsif self.touched_at < 90.days.ago
|
172
|
+
"Expired"
|
173
|
+
else
|
174
|
+
"Active"
|
175
|
+
end
|
176
|
+
end
|
161
177
|
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -19,7 +19,7 @@ class Property < MLS::Model
|
|
19
19
|
has_many :image_orderings, as: :subject
|
20
20
|
has_many :data, as: :subject
|
21
21
|
has_many :photos, through: :image_orderings, source: :image
|
22
|
-
has_many :
|
22
|
+
has_many :services, as: :subject
|
23
23
|
|
24
24
|
has_many :uses
|
25
25
|
# has_and_belongs_to_many :uses
|
@@ -48,6 +48,12 @@ class Property < MLS::Model
|
|
48
48
|
def latitude
|
49
49
|
location.y
|
50
50
|
end
|
51
|
+
|
52
|
+
def is_elite_for_account_ids?(*account_ids)
|
53
|
+
return false unless self.elite_account_ids && self.elite_account_ids.length > 0
|
54
|
+
account_ids = Array(account_ids).flatten
|
55
|
+
(self.elite_account_ids & account_ids).length > 0
|
56
|
+
end
|
51
57
|
|
52
58
|
def display_description
|
53
59
|
return description if description.present?
|
@@ -122,6 +128,7 @@ class Property < MLS::Model
|
|
122
128
|
region = neighborhood_region
|
123
129
|
region ||= city_region
|
124
130
|
region ||= market
|
131
|
+
region ||= regions.where(depth: true).sort_by(&:depth).reverse.first
|
125
132
|
region
|
126
133
|
end
|
127
134
|
|
@@ -134,13 +141,28 @@ class Property < MLS::Model
|
|
134
141
|
|
135
142
|
def city_region
|
136
143
|
return @city_region if defined? @city_region
|
137
|
-
@city_region = fetch_region(:type =>
|
144
|
+
@city_region = fetch_region(:type => Region::CITY_TYPES)
|
145
|
+
end
|
146
|
+
|
147
|
+
def state_region
|
148
|
+
return @state_region if defined? @state_region
|
149
|
+
@state_region = fetch_region(:type => Region::STATE_TYPES)
|
138
150
|
end
|
139
151
|
|
140
152
|
def market
|
141
153
|
return @market if defined? @market
|
142
154
|
@market = fetch_region(:is_market => true)
|
143
155
|
end
|
156
|
+
|
157
|
+
def human_breadcrumbs
|
158
|
+
[
|
159
|
+
neighborhood.present? ? neighborhood : neighborhood_region&.name,
|
160
|
+
city.present? ? city : (city_region&.name || regions.select{|r|
|
161
|
+
r.depth && r.depth >= 3
|
162
|
+
}.first&.name),
|
163
|
+
state.present? ? state : state_region&.slug&.split("/")&.last&.upcase
|
164
|
+
].compact
|
165
|
+
end
|
144
166
|
|
145
167
|
def flagship
|
146
168
|
return @flagship if defined? @flagship
|
@@ -152,7 +174,13 @@ class Property < MLS::Model
|
|
152
174
|
if params[0][0] == :query
|
153
175
|
regions.to_a.find{|r| r.name == params[0][1]}
|
154
176
|
else
|
155
|
-
regions.to_a.find{|r|
|
177
|
+
regions.to_a.find{|r|
|
178
|
+
if params[0][1].is_a? Array
|
179
|
+
params[0][1].include? (r[params[0][0]])
|
180
|
+
else
|
181
|
+
r[params[0][0]] == params[0][1]
|
182
|
+
end
|
183
|
+
}
|
156
184
|
end
|
157
185
|
end
|
158
186
|
end
|
File without changes
|
File without changes
|
@@ -4,6 +4,8 @@ class Region < MLS::Model
|
|
4
4
|
|
5
5
|
self.inheritance_column = nil
|
6
6
|
|
7
|
+
COUNTRY_TYPES = ["Monarchy", "Republic"]
|
8
|
+
STATE_TYPES = ["State", "Territory", "Commonwealth", "Province"]
|
7
9
|
CITY_TYPES = ["City", "Municipality", "Village", "Rural Municipality", "Town", "Resort Village", "Community Government"]
|
8
10
|
|
9
11
|
belongs_to :cover_photo, :class_name => 'Image'
|
@@ -20,8 +22,12 @@ class Region < MLS::Model
|
|
20
22
|
def name
|
21
23
|
if common_name.try(:[], 'eng')
|
22
24
|
common_name['eng'].is_a?(Array) ? common_name['eng'].first : common_name['eng']
|
23
|
-
|
25
|
+
elsif official_name.try(:[], 'eng')
|
24
26
|
official_name['eng'].is_a?(Array) ? official_name['eng'].first : official_name['eng']
|
27
|
+
elsif common_name && common_name.size > 0
|
28
|
+
common_name.values.first
|
29
|
+
else
|
30
|
+
official_name.values.first
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
@@ -53,4 +59,4 @@ class Region < MLS::Model
|
|
53
59
|
result
|
54
60
|
end
|
55
61
|
|
56
|
-
end
|
62
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Search < MLS::Model
|
2
|
+
|
3
|
+
STATUS_OPTIONS = %w(active hold cold closed)
|
4
|
+
STAGE_OPTIONS = %w(initiated contacted delivered connected toured loi signed coworking)
|
5
|
+
BUDGET_UNITS = %w(per_month per_year per_sqft_per_year)
|
6
|
+
TERMS = %w(<1 1-2 3-5 5+ flexible)
|
7
|
+
MOVE_INS = %w(<3 3-6 6-12 12+ flexible)
|
8
|
+
|
9
|
+
belongs_to :account
|
10
|
+
belongs_to :broker, class_name: "Account"
|
11
|
+
belongs_to :manager, class_name: "Account"
|
12
|
+
belongs_to :lead
|
13
|
+
|
14
|
+
has_many :suggestions
|
15
|
+
has_many :email_digests
|
16
|
+
has_many :tasks, :as => :subject
|
17
|
+
|
18
|
+
accepts_nested_attributes_for :account
|
19
|
+
|
20
|
+
def name
|
21
|
+
read_attribute(:name) || account&.company || account&.name
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json(options={})
|
25
|
+
output = super(options)
|
26
|
+
output = JSON.parse(super)
|
27
|
+
output["filter"] = read_attribute(:filter)
|
28
|
+
output.to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
def filter
|
32
|
+
JSON.parse (read_attribute(:filter) || {}).to_json, object_class: OpenStruct
|
33
|
+
end
|
34
|
+
|
35
|
+
def regions
|
36
|
+
Region.where(id: self.region_ids)
|
37
|
+
end
|
38
|
+
|
39
|
+
def move_in_units(value=nil)
|
40
|
+
value ||= self.move_in
|
41
|
+
case value
|
42
|
+
when "<1"
|
43
|
+
"month"
|
44
|
+
when "flexible"
|
45
|
+
""
|
46
|
+
else
|
47
|
+
"months"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def term_units(value=nil)
|
52
|
+
value ||= self.term
|
53
|
+
case value
|
54
|
+
when "<1"
|
55
|
+
"year"
|
56
|
+
when "flexible"
|
57
|
+
""
|
58
|
+
else
|
59
|
+
"years"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Site < MLS::Model
|
2
|
+
|
3
|
+
belongs_to :region
|
4
|
+
belongs_to :cover_photo, :class_name => 'Image'
|
5
|
+
belongs_to :logo, :class_name => 'Image'
|
6
|
+
|
7
|
+
has_many :ownerships, as: :asset
|
8
|
+
has_many :accounts, through: :ownerships, source: :account, inverse_of: :sites
|
9
|
+
has_many :services, as: :subject
|
10
|
+
|
11
|
+
def contacts
|
12
|
+
if ownerships.loaded?
|
13
|
+
@contacts ||= ownerships.select{|o| o.receives_inquiries }.map(&:account)
|
14
|
+
else
|
15
|
+
@contacts ||= ownerships.eager_load(:account).filter(:receives_inquiries => true).map(&:account)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def lead_contacts
|
20
|
+
if ownerships.loaded?
|
21
|
+
@lead_contacts ||= ownerships.select{|o| o.lead}.map(&:account)
|
22
|
+
else
|
23
|
+
@lead_contacts ||= ownerships.eager_load(:account).filter(:lead => true).map(&:account)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Subscription < MLS::Model
|
2
|
+
self.inheritance_column = nil
|
3
|
+
|
4
|
+
has_and_belongs_to_many :accounts
|
5
|
+
has_many :invoices
|
6
|
+
has_many :services
|
7
|
+
belongs_to :organization
|
8
|
+
belongs_to :billing_contact, class_name: "Account"
|
9
|
+
belongs_to :credit_card
|
10
|
+
|
11
|
+
has_and_belongs_to_many :invoice_recipients, class_name: 'EmailAddress'
|
12
|
+
|
13
|
+
accepts_nested_attributes_for :services
|
14
|
+
|
15
|
+
def cost
|
16
|
+
read_attribute(:cost) / 100.0 if read_attribute(:cost)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/builder'
|
3
|
+
|
4
|
+
module MLS
|
5
|
+
module Rack
|
6
|
+
class Proxy
|
7
|
+
|
8
|
+
def self.new
|
9
|
+
app = super
|
10
|
+
::Rack::Builder.new do
|
11
|
+
use(ActionDispatch::Cookies)
|
12
|
+
use(ActionDispatch::Session::CookieStore, {
|
13
|
+
key: Rails.application.config.session_options[:key],
|
14
|
+
path: '/',
|
15
|
+
secret: Rails.application.secrets[:secret_key_base]
|
16
|
+
})
|
17
|
+
run app
|
18
|
+
end.to_app
|
19
|
+
end
|
20
|
+
|
21
|
+
def extract_http_request_headers(env)
|
22
|
+
headers = env.reject do |k, v|
|
23
|
+
!(/^HTTP_[A-Z_]+$/ === k) || v.nil?
|
24
|
+
end.map do |k, v|
|
25
|
+
[k.sub(/^HTTP_/, "").gsub("_", "-"), v]
|
26
|
+
end.inject({}) do |hash, k_v|
|
27
|
+
k, v = k_v
|
28
|
+
hash[k] = v
|
29
|
+
hash
|
30
|
+
end
|
31
|
+
|
32
|
+
headers.delete_if {|key, value| ["HOST", "API-VERSION", "CONNECTION", "VERSION"].include?(key) }
|
33
|
+
x_forwarded_for = (headers["X-Forwarded-For"].to_s.split(/, +/) << env["REMOTE_ADDR"]).join(", ")
|
34
|
+
|
35
|
+
headers.merge!("X-Forwarded-For" => x_forwarded_for)
|
36
|
+
end
|
37
|
+
|
38
|
+
def call(env)
|
39
|
+
request = Net::HTTP.const_get(env['REQUEST_METHOD'].capitalize).new(env['PATH_INFO'] + '?' + env['QUERY_STRING'])
|
40
|
+
request.initialize_http_header(extract_http_request_headers(env))
|
41
|
+
|
42
|
+
if request.request_body_permitted?
|
43
|
+
if env['TRANSFER-ENCODING'] == 'chunked'
|
44
|
+
request.body_stream = env['rack.input']
|
45
|
+
elsif env['CONTENT_LENGTH']
|
46
|
+
request.body = env['rack.input'].read
|
47
|
+
end
|
48
|
+
end
|
49
|
+
request['Content-Type'] = env['CONTENT_TYPE']
|
50
|
+
|
51
|
+
response = MLS::Model.connection_pool.with_connection do |conn|
|
52
|
+
with_cookie_store(env) do
|
53
|
+
request_uri = "http#{conn.instance_variable_get(:@connection).use_ssl ? 's' : ''}://#{conn.instance_variable_get(:@connection).host}#{conn.instance_variable_get(:@connection).port != 80 ? (conn.instance_variable_get(:@connection).port == 443 && conn.instance_variable_get(:@connection).use_ssl ? '' : ":#{conn.instance_variable_get(:@connection).port}") : ''}#{request.path}"
|
54
|
+
request['Cookie'] = Thread.current[:sunstone_cookie_store].cookie_header_for(request_uri)
|
55
|
+
conn.instance_variable_get(:@connection).send(:request_headers).each { |k, v| request[k] = v if ['Api-Version', 'Api-Key'].include?(k) }
|
56
|
+
|
57
|
+
conn.instance_variable_get(:@connection).instance_variable_get(:@connection).request(request)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
response_headers = {}
|
61
|
+
response.each_header { |k, v| response_headers[k] = v unless k == 'transfer-encoding' }
|
62
|
+
|
63
|
+
[response.code, response_headers, [response.body]]
|
64
|
+
end
|
65
|
+
|
66
|
+
def with_cookie_store(env)
|
67
|
+
store = CookieStore::HashStore.new
|
68
|
+
store.add_from_json(env['rack.session']['cookie_store']) if env['rack.session']['cookie_store']
|
69
|
+
Thread.current[:sunstone_cookie_store] = store
|
70
|
+
result = yield
|
71
|
+
Thread.current[:sunstone_cookie_store] = nil
|
72
|
+
env['rack.session']['cookie_store'] = store.to_json
|
73
|
+
result
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/mls/railtie.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# See notes from 'active_record/railtie'
|
2
|
+
require "action_controller/railtie"
|
3
|
+
|
4
|
+
class MLS::Railtie < Rails::Railtie
|
5
|
+
|
6
|
+
config.mls = ActiveSupport::OrderedOptions.new
|
7
|
+
|
8
|
+
config.action_dispatch.rescue_responses.merge!(
|
9
|
+
"Sunstone::Exception::NotFound" => :not_found,
|
10
|
+
"Sunstone::Exception::Unauthorized" => :unauthorized,
|
11
|
+
"Sunstone::Exception::Gone" => :gone
|
12
|
+
)
|
13
|
+
|
14
|
+
initializer 'mls' do |app|
|
15
|
+
|
16
|
+
url = app.config.mls.fetch('url') { app.secrets.mls }
|
17
|
+
user_agent = []
|
18
|
+
user_agent << app.config.mls.fetch('user_agent') {
|
19
|
+
app.class.name.split('::')[0..-2].join('::')
|
20
|
+
}
|
21
|
+
user_agent << "Rails/#{Rails.version}"
|
22
|
+
|
23
|
+
|
24
|
+
MLS::Model.establish_connection({
|
25
|
+
adapter: 'sunstone',
|
26
|
+
url: url,
|
27
|
+
user_agent: user_agent.compact.join(' ')
|
28
|
+
})
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/mls.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "mls"
|
6
|
-
s.version = '1.
|
6
|
+
s.version = '1.6.0'
|
7
7
|
s.authors = ["Jon Bracy", "James R. Bracy"]
|
8
8
|
s.email = ["jon@42floors.com", "james@42floors.com"]
|
9
9
|
s.homepage = "http://mls.42floors.com"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Bracy
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-01-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -239,7 +239,8 @@ description: Ruby library for integrating with the 42Floors MLS
|
|
239
239
|
email:
|
240
240
|
- jon@42floors.com
|
241
241
|
- james@42floors.com
|
242
|
-
executables:
|
242
|
+
executables:
|
243
|
+
- mls
|
243
244
|
extensions: []
|
244
245
|
extra_rdoc_files: []
|
245
246
|
files:
|
@@ -247,53 +248,64 @@ files:
|
|
247
248
|
- Gemfile
|
248
249
|
- README.rdoc
|
249
250
|
- Rakefile
|
251
|
+
- bin/mls
|
250
252
|
- lib/mls.rb
|
251
|
-
- lib/mls/
|
252
|
-
- lib/mls/
|
253
|
-
- lib/mls/
|
254
|
-
- lib/mls/
|
255
|
-
- lib/mls/api_key.rb
|
253
|
+
- lib/mls/cli.rb
|
254
|
+
- lib/mls/cli/documents.rb
|
255
|
+
- lib/mls/cli/storage.rb
|
256
|
+
- lib/mls/cli/storage/s3.rb
|
256
257
|
- lib/mls/comment.rb
|
257
|
-
- lib/mls/
|
258
|
-
- lib/mls/
|
259
|
-
- lib/mls/
|
260
|
-
- lib/mls/
|
261
|
-
- lib/mls/
|
262
|
-
- lib/mls/
|
263
|
-
- lib/mls/
|
264
|
-
- lib/mls/
|
265
|
-
- lib/mls/
|
266
|
-
- lib/mls/
|
267
|
-
- lib/mls/
|
268
|
-
- lib/mls/
|
269
|
-
- lib/mls/
|
270
|
-
- lib/mls/
|
271
|
-
- lib/mls/
|
272
|
-
- lib/mls/
|
273
|
-
- lib/mls/
|
274
|
-
- lib/mls/
|
275
|
-
- lib/mls/
|
276
|
-
- lib/mls/
|
277
|
-
- lib/mls/
|
278
|
-
- lib/mls/
|
279
|
-
- lib/mls/
|
280
|
-
- lib/mls/
|
281
|
-
- lib/mls/
|
282
|
-
- lib/mls/
|
283
|
-
- lib/mls/
|
284
|
-
- lib/mls/
|
285
|
-
- lib/mls/
|
286
|
-
- lib/mls/
|
287
|
-
- lib/mls/
|
288
|
-
- lib/mls/
|
289
|
-
- lib/mls/
|
290
|
-
- lib/mls/
|
291
|
-
- lib/mls/
|
292
|
-
- lib/mls/
|
293
|
-
- lib/mls/
|
294
|
-
- lib/mls/
|
295
|
-
- lib/mls/
|
296
|
-
- lib/mls/
|
258
|
+
- lib/mls/models/account.rb
|
259
|
+
- lib/mls/models/accounts_region.rb
|
260
|
+
- lib/mls/models/action.rb
|
261
|
+
- lib/mls/models/address.rb
|
262
|
+
- lib/mls/models/api_key.rb
|
263
|
+
- lib/mls/models/coworking_space.rb
|
264
|
+
- lib/mls/models/credit_card.rb
|
265
|
+
- lib/mls/models/datum.rb
|
266
|
+
- lib/mls/models/document.rb
|
267
|
+
- lib/mls/models/email.rb
|
268
|
+
- lib/mls/models/email_address.rb
|
269
|
+
- lib/mls/models/email_digest.rb
|
270
|
+
- lib/mls/models/event.rb
|
271
|
+
- lib/mls/models/flyer.rb
|
272
|
+
- lib/mls/models/geometry.rb
|
273
|
+
- lib/mls/models/image_ordering.rb
|
274
|
+
- lib/mls/models/impression_count.rb
|
275
|
+
- lib/mls/models/inquiry.rb
|
276
|
+
- lib/mls/models/invoice.rb
|
277
|
+
- lib/mls/models/lead.rb
|
278
|
+
- lib/mls/models/listing.rb
|
279
|
+
- lib/mls/models/locality.rb
|
280
|
+
- lib/mls/models/metadatum.rb
|
281
|
+
- lib/mls/models/mistake.rb
|
282
|
+
- lib/mls/models/organization.rb
|
283
|
+
- lib/mls/models/ownership.rb
|
284
|
+
- lib/mls/models/phone.rb
|
285
|
+
- lib/mls/models/property.rb
|
286
|
+
- lib/mls/models/recommendation.rb
|
287
|
+
- lib/mls/models/reference.rb
|
288
|
+
- lib/mls/models/region.rb
|
289
|
+
- lib/mls/models/search.rb
|
290
|
+
- lib/mls/models/service.rb
|
291
|
+
- lib/mls/models/session.rb
|
292
|
+
- lib/mls/models/site.rb
|
293
|
+
- lib/mls/models/slug.rb
|
294
|
+
- lib/mls/models/source.rb
|
295
|
+
- lib/mls/models/space.rb
|
296
|
+
- lib/mls/models/stat.rb
|
297
|
+
- lib/mls/models/subscription.rb
|
298
|
+
- lib/mls/models/suggestion.rb
|
299
|
+
- lib/mls/models/task.rb
|
300
|
+
- lib/mls/models/team.rb
|
301
|
+
- lib/mls/models/tim_alert.rb
|
302
|
+
- lib/mls/models/time_log.rb
|
303
|
+
- lib/mls/models/use.rb
|
304
|
+
- lib/mls/models/vendor.rb
|
305
|
+
- lib/mls/models/view.rb
|
306
|
+
- lib/mls/models/webpage.rb
|
307
|
+
- lib/mls/rack/proxy.rb
|
308
|
+
- lib/mls/railtie.rb
|
297
309
|
- mls.gemspec
|
298
310
|
- test/fixtures/flyer.pdf
|
299
311
|
- test/mls/attribute_test.rb
|
@@ -319,7 +331,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
319
331
|
version: '0'
|
320
332
|
requirements: []
|
321
333
|
rubyforge_project: mls
|
322
|
-
rubygems_version: 2.
|
334
|
+
rubygems_version: 2.6.11
|
323
335
|
signing_key:
|
324
336
|
specification_version: 4
|
325
337
|
summary: 42Floors MLS Client
|
data/lib/mls/action.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
class Action < MLS::Model
|
2
|
-
self.inheritance_column = nil
|
3
|
-
|
4
|
-
belongs_to :event
|
5
|
-
belongs_to :subject, :polymorphic => true
|
6
|
-
|
7
|
-
has_many :mistakes
|
8
|
-
has_many :metadata, foreign_key: :event_id, primary_key: :event_id
|
9
|
-
|
10
|
-
def self.by_performer(filter)
|
11
|
-
req = Net::HTTP::Get.new("/actions/by_performer")
|
12
|
-
req.body = {
|
13
|
-
where: filter
|
14
|
-
}.to_json
|
15
|
-
JSON.parse(connection.instance_variable_get(:@connection).send_request(req).body)
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
data/lib/mls/email_digest.rb
DELETED
data/lib/mls/lead.rb
DELETED
data/lib/mls/membership.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
class Membership < MLS::Model
|
2
|
-
self.inheritance_column = nil
|
3
|
-
|
4
|
-
has_many :accounts
|
5
|
-
has_many :invoices
|
6
|
-
has_many :subscriptions
|
7
|
-
belongs_to :organization
|
8
|
-
belongs_to :billing_contact, class_name: "Account"
|
9
|
-
belongs_to :credit_card
|
10
|
-
belongs_to :sourced_by, class_name: "Account"
|
11
|
-
has_and_belongs_to_many :invoice_recipients, class_name: 'EmailAddress'
|
12
|
-
|
13
|
-
accepts_nested_attributes_for :subscriptions
|
14
|
-
|
15
|
-
def rate
|
16
|
-
subscriptions.select{|x| !x.ends_at}.map(&:cost).compact.sum
|
17
|
-
end
|
18
|
-
|
19
|
-
def costs
|
20
|
-
(read_attribute(:costs) || {}).with_indifferent_access
|
21
|
-
end
|
22
|
-
|
23
|
-
def value
|
24
|
-
read_attribute(:value) / 100.0 if read_attribute(:value)
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
data/lib/mls/subscription.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
class Subscription < MLS::Model
|
2
|
-
self.inheritance_column = nil
|
3
|
-
|
4
|
-
belongs_to :membership
|
5
|
-
belongs_to :subject, polymorphic: true
|
6
|
-
belongs_to :credit_card
|
7
|
-
|
8
|
-
def name
|
9
|
-
case self.type
|
10
|
-
when "unlimited"
|
11
|
-
"Unlimited Premium Listings"
|
12
|
-
when "premium"
|
13
|
-
"Premium Listings"
|
14
|
-
when "elite"
|
15
|
-
"Elite Account"
|
16
|
-
when "coworking"
|
17
|
-
"Coworking Space"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def cost
|
22
|
-
read_attribute(:cost) / 100.0 if read_attribute(:cost)
|
23
|
-
end
|
24
|
-
end
|