mls 1.5.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9caa8aa44855ec88845d59e8732212c33e9ae86f
4
- data.tar.gz: e443bbd96ee37784f7bd360d185cafab43e4d0d4
3
+ metadata.gz: d679db7d9456ed2f5924a612fd51157607a5c360
4
+ data.tar.gz: 869b5a1f4d647eb414827322bc9904cb68220488
5
5
  SHA512:
6
- metadata.gz: c0b278d87cf5e782045105c1f8461a8feda501f74da7af7bc8cc33a14d1d38e614632073609b208f1f6aaf978f029a0680f11e6fa10cfc088374fb6640581ef5
7
- data.tar.gz: 19ebd1f220371778d1c74a5ebfde587bfea7c076f62fac80c912d6b966a34adc710ed459b557bf58bae3bb03466e6016c4fde716bee6ab8c21d423d22048e699
6
+ metadata.gz: ec8233dc1a01a4341d793e112bb67540796eb3d5ec90752704213fff4075755e8ad81e7c497bce35a23c47ca81fe0f4cb496f30a0a6150249bd08fc87a088608
7
+ data.tar.gz: ba2ae50b4822afac5febe29d8bcca90a6af7cd17e5a0d283f29f2ed8d717cbd8571674ae1e06554f0baca2a8b17ffa6304a613f1d6409666e1c65f0e8b18a3f3
data/lib/mls.rb CHANGED
@@ -1,4 +1,7 @@
1
+ require 'phony'
1
2
  require 'sunstone'
3
+ require 'arel/extensions'
4
+ require 'bcrypt'
2
5
 
3
6
  module MLS
4
7
 
@@ -98,8 +101,12 @@ module MLS::Slugger
98
101
  def find(*ids)
99
102
  friendly = -> (id) { id.respond_to?(:to_i) && id.to_i.to_s != id.to_s }
100
103
  return super if ids.size > 1 || !ids.all? { |x| friendly.call(x) }
101
-
102
- find_by_slug!(ids.first)
104
+
105
+ if ids.first.include?("@")
106
+ self.filter(email_addresses: {address: ids.first}).first
107
+ else
108
+ find_by_slug!(ids.first)
109
+ end
103
110
  end
104
111
 
105
112
  end
@@ -149,31 +156,6 @@ module MLS::Avatar
149
156
  belongs_to :avatar, :class_name => 'Image'
150
157
  end
151
158
 
152
- def avatar_url(options={})
153
- return nil unless avatar_hash_key
154
-
155
- options.reverse_merge!({
156
- :style => nil,
157
- :bg => nil,
158
- :protocol => 'https',
159
- :format => "jpg",
160
- :host => MLS.image_host
161
- });
162
-
163
- url_params = { s: options[:style], bg: options[:bg] }.select{ |k, v| v }
164
-
165
- if options[:protocol] == :relative # Protocol Relative
166
- result = '//'
167
- else options[:protocol]
168
- result = "#{options[:protocol]}://"
169
- end
170
-
171
- result += "#{options[:host]}/#{avatar_hash_key}.#{options[:format]}"
172
- result += "?#{url_params.to_param}" if url_params.size > 0
173
-
174
- result
175
- end
176
-
177
159
  end
178
160
 
179
161
  Dir.glob(File.join(File.dirname(__FILE__), 'mls', '*.rb'), &method(:require))
@@ -3,21 +3,29 @@ class Account < MLS::Model
3
3
  include MLS::Slugger
4
4
  include MLS::Avatar
5
5
 
6
- has_one :lead, foreign_key: :account_id
7
-
8
6
  belongs_to :organization
9
- belongs_to :green_sheet, :foreign_key => :green_sheet_uuid
7
+ belongs_to :membership
10
8
 
11
9
  has_many :tasks
12
10
  has_many :sources
13
- has_many :agencies, :inverse_of => :agent, :foreign_key => :agent_id
11
+ has_many :ownerships, :inverse_of => :account, :dependent => :delete_all
12
+ has_many :assets, through: :ownerships
13
+ has_many :coworking_spaces, through: :ownerships, source: :asset, source_type: 'CoworkingSpace'
14
+ has_many :listings, through: :ownerships, source: :asset, source_type: 'Listing', inverse_of: :accounts
15
+ has_many :email_digests
16
+ has_many :subscriptions, as: :subject
17
+ has_many :leads
14
18
 
15
- has_and_belongs_to_many :regions, :foreign_key => :agent_id
19
+ has_many :credit_cards
16
20
 
17
21
  has_many :email_addresses do
18
22
  def primary
19
23
  # For cases where the number is not primary we order
20
- order(:primary => :desc).first
24
+ if loaded?
25
+ select{|x| x.primary}.first
26
+ else
27
+ order(:primary => :desc).first
28
+ end
21
29
  end
22
30
  end
23
31
 
@@ -25,30 +33,126 @@ class Account < MLS::Model
25
33
 
26
34
  def primary
27
35
  # For cases where the number is not primary we order
28
- order(:primary => :desc).first
36
+ if loaded?
37
+ select{|x| x.primary}.first
38
+ else
39
+ order(:primary => :desc).first
40
+ end
29
41
  end
30
42
 
31
43
  end
32
44
 
45
+ has_and_belongs_to_many :advertised_regions, join_table: 'accounts_regions_advertised', class_name: 'Region'
46
+ has_and_belongs_to_many :inquiries
47
+ has_and_belongs_to_many :teams
48
+
49
+ attr_accessor :password, :password_required
50
+ accepts_nested_attributes_for :phones, :email_addresses
51
+
52
+ validates :password, confirmation: true, if: Proc.new {|a| (!a.persisted? && a.password_required?) || !a.password.nil? }
53
+ validates :password, length: { minimum: 6 }, if: :password
54
+ validates :password_confirmation, presence: true, if: :password
55
+
56
+ def regions
57
+ Region.filter(id: {in: self.advertised_region_ids})
58
+ end
59
+
60
+ def city_regions
61
+ advertised_regions.filter(type: Region::CITY_TYPES).order(listings_count: :desc)
62
+ end
63
+
64
+ def properties
65
+ Property.where(listings: {ownerships: {account_id: self.id}})
66
+ end
67
+
68
+ def tim_alerts?
69
+ self.membership&.subscriptions&.filter(started_at: true, status: {not: "closed"}, type: "tim_alerts", subject_id: self.id, subject_type: "Account")&.count.try(:>, 0)
70
+ end
71
+
72
+ def unlimited?
73
+ self.membership&.subscriptions&.filter(started_at: true, status: {not: "closed"}, type: "unlimited", subject_id: self.id, subject_type: "Account")&.count.try(:>, 0)
74
+ end
75
+
76
+ def paying?
77
+ self.membership&.subscriptions&.filter(started_at: true, status: {not: "closed"})&.count.try(:>, 0)
78
+ end
79
+
80
+ def password_required?
81
+ @password_required != false
82
+ end
83
+
84
+ def password=(pass)
85
+ @password = pass
86
+ self.password_digest = BCrypt::Password.create(pass)
87
+ end
88
+
33
89
  def email_address
34
- if email_addresses.loaded?
35
- email_addresses.to_a.find{|p| p.primary }.try(:address)
36
- else
37
- email_addresses.primary.try(:address)
90
+ email_addresses.to_a.find{|p| p.primary }.try(:address)
91
+ end
92
+
93
+ def regions_attributes=(regions_attrs)
94
+ # regions.clear was trying to destroy all regions going to "/accounts_regions/" method = Destroy
95
+ AccountsRegion.where(:agent_id => self.id).destroy_all
96
+ return if regions_attrs.nil?
97
+ regions_attrs.each do |attrs|
98
+ region = Region.find(attrs["id"])
99
+ regions.push(region)
38
100
  end
39
101
  end
40
102
 
41
103
  def phone
42
- if phones.loaded?
43
- phones.to_a.find{|p| p.primary }.try(:number)
44
- else
45
- phones.primary.try(:number)
46
- end
104
+ (phones.to_a.find{|p| p.primary } || phones.first).try(:number)
47
105
  end
48
106
 
107
+ def role?(*compare_roles)
108
+ (roles & compare_roles).any?
109
+ end
110
+ alias_method :roles?, :role?
111
+
49
112
  def company_name
50
113
  return organization.name if organization
51
114
  return company
52
115
  end
116
+
117
+ def merge_in(account_id)
118
+ req = Net::HTTP::Put.new("/accounts/#{self.id}/merge")
119
+ req.body = { account_id: account_id }.to_json
120
+ Account.connection.instance_variable_get(:@connection).send_request(req)
121
+ return true
122
+ rescue Sunstone::Exception::NotFound
123
+ return false
124
+ end
125
+
126
+ def self.send_reset_password_email(url, email_address)
127
+ req = Net::HTTP::Post.new("/accounts/password")
128
+ req.body = { email_address: email_address, url: url }.to_json
129
+ Account.connection.instance_variable_get(:@connection).send_request(req)
130
+ end
131
+
132
+ def self.update_password(token, password, password_confirmation)
133
+ req = Net::HTTP::Put.new("/accounts/password")
134
+ req.body = {
135
+ token: token,
136
+ password: password,
137
+ password_confirmation: password_confirmation
138
+ }.to_json
139
+ Account.connection.instance_variable_get(:@connection).send_request(req)
140
+ end
141
+
142
+ def self.confirm(token)
143
+ req = Net::HTTP::Post.new("/accounts/confirm")
144
+ req.body = { token: token }.to_json
145
+ Account.connection.instance_variable_get(:@connection).send_request(req)
146
+ return true
147
+ rescue Sunstone::Exception::NotFound
148
+ return false
149
+ end
150
+
151
+ def send_confirmation_email(url)
152
+ req = Net::HTTP::Post.new("/accounts/#{self.id}/confirm")
153
+ req.body = {url: url}.to_json
154
+ Account.connection.instance_variable_get(:@connection).send_request(req)
155
+ end
156
+
53
157
 
54
158
  end
@@ -0,0 +1,6 @@
1
+ class AccountsRegion < MLS::Model
2
+
3
+ belongs_to :account
4
+ belongs_to :region
5
+
6
+ end
@@ -0,0 +1,18 @@
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
@@ -0,0 +1,5 @@
1
+ class ApiKey < MLS::Model
2
+
3
+ belongs_to :account
4
+
5
+ end
@@ -4,15 +4,29 @@ class CoworkingSpace < MLS::Model
4
4
 
5
5
  belongs_to :organization
6
6
  belongs_to :property
7
+ belongs_to :membership
7
8
  has_many :image_orderings, as: :subject
8
9
  has_many :photos, through: :image_orderings, source: :image
9
10
  has_many :spaces
10
11
  has_many :addresses, :through => :property
11
12
 
12
- def name
13
+ has_many :ownerships, as: :asset
14
+ has_many :accounts, through: :ownerships
15
+
16
+ accepts_nested_attributes_for :spaces, :ownerships, :accounts
17
+
18
+ def display_name
13
19
  output = organization.name
14
20
  output += " - " + read_attribute(:name) if read_attribute(:name)
15
21
  output
16
22
  end
23
+
24
+ def longitude
25
+ location.x
26
+ end
27
+
28
+ def latitude
29
+ location.y
30
+ end
17
31
 
18
- end
32
+ end
@@ -0,0 +1,11 @@
1
+ class CreditCard < MLS::Model
2
+
3
+ belongs_to :account
4
+
5
+ def name
6
+ string = "&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull;&bull; &bull;" if self.brand == "American Express"
7
+ string ||= "&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; "
8
+ string += self.last4
9
+ end
10
+
11
+ end
@@ -0,0 +1,5 @@
1
+ class Datum < MLS::Model
2
+
3
+ belongs_to :subject, :polymorphic => true
4
+
5
+ end
@@ -1,5 +1,7 @@
1
1
  class Document < MLS::Model
2
2
 
3
+ has_many :image_orderings, foreign_key: :image_id
4
+
3
5
  def self.create(file)
4
6
  if doc = find_matching(file)
5
7
  doc
@@ -16,13 +18,17 @@ class Document < MLS::Model
16
18
  end
17
19
 
18
20
  def url(style=:original)
19
- MLS.config['document_host'] + path(style)
21
+ MLS.config['document_host'] + '/' + path(style)
20
22
  end
21
23
 
22
24
  def path(style=:original)
23
- "/documents/#{hash_key}/#{style}#{File.extname(filename)}"
25
+ "#{partition(style == :original ? hash_key : "#{hash_key}-#{style}")}"
24
26
  end
25
27
 
28
+ def partition(value)
29
+ split = value.scan(/.{1,4}/)
30
+ split.shift(4).join("/") + split.join("")
31
+ end
26
32
 
27
33
  def width
28
34
  return nil if !dimensions
@@ -59,30 +65,6 @@ class Document < MLS::Model
59
65
  end
60
66
 
61
67
  class Image < Document
62
-
63
- def url(options={})
64
- options.reverse_merge!({
65
- :style => nil,
66
- :bg => nil,
67
- :protocol => 'https',
68
- :format => "jpg",
69
- :host => MLS.image_host
70
- });
71
-
72
- url_params = {s: options[:style], bg: options[:bg]}.select{ |k, v| v }
73
-
74
- if options[:protocol] == :relative # Protocol Relative
75
- result = '//'
76
- else options[:protocol]
77
- result = "#{options[:protocol]}://"
78
- end
79
-
80
- result += "#{options[:host]}/#{hash_key}.#{options[:format]}"
81
- result += "?#{url_params.to_param}" if url_params.size > 0
82
-
83
- result
84
- end
85
-
86
68
  end
87
69
 
88
70
  class PDF < Document
@@ -1,6 +1,7 @@
1
1
  class Email < MLS::Model
2
2
 
3
3
  belongs_to :source
4
+ has_many :tasks, :as => :subject, :inverse_of => :subject
4
5
  has_and_belongs_to_many :attachments, :class_name => 'Document'
5
6
 
6
7
  def from
@@ -12,7 +13,7 @@ class Email < MLS::Model
12
13
  end
13
14
 
14
15
  def name
15
- from
16
+ from_address || from
16
17
  end
17
18
 
18
19
  def to
@@ -3,6 +3,11 @@ class EmailAddress < MLS::Model
3
3
 
4
4
  TYPES = %w(work personal other)
5
5
 
6
+ has_many :emails
7
+
6
8
  belongs_to :account
7
9
 
10
+ def name
11
+ address
12
+ end
8
13
  end
@@ -0,0 +1,10 @@
1
+ class EmailDigest < MLS::Model
2
+
3
+ belongs_to :account
4
+ accepts_nested_attributes_for :account
5
+
6
+ def filter
7
+ (read_attribute(:filter) || {}).with_indifferent_access
8
+ end
9
+
10
+ end
@@ -4,17 +4,42 @@ class Event < MLS::Model
4
4
 
5
5
  belongs_to :account
6
6
  belongs_to :task
7
+ belongs_to :api_key
7
8
 
8
- has_many :event_actions
9
+ has_many :actions
9
10
 
10
11
  has_many :regards
11
12
 
12
- def actions
13
- event_actions.map(&:action)
14
- end
13
+ enum type: { create: 0, update: 1, delete: 2 }, _suffix: true
15
14
 
16
15
  def regarding
17
16
  regards.map(&:thing)
18
17
  end
19
18
 
20
- end
19
+ def encapsulate(&block)
20
+ Thread.current[:sunstone_headers] ||= {}
21
+ Thread.current[:sunstone_headers]['Event-Id'] = self.id
22
+ yield
23
+ self
24
+ ensure
25
+ Thread.current[:sunstone_headers].delete('Event-Id')
26
+ end
27
+
28
+ # Allow you to encapsulate all modification to be attached to a single event
29
+ #
30
+ # Event.encapsulate(source: '...', source_type: 'API') do
31
+ # ...
32
+ # end
33
+ #
34
+ # Returns the event is needed in the future
35
+ def self.encapsulate(options={}, &block)
36
+ event = Event.create!(options)
37
+ Thread.current[:sunstone_headers] ||= {}
38
+ Thread.current[:sunstone_headers]['Event-Id'] = event.id
39
+ yield
40
+ event
41
+ ensure
42
+ Thread.current[:sunstone_headers].try(:delete, 'Event-Id')
43
+ end
44
+
45
+ end