ffcrm_cloudfuji 0.3.1 → 0.4.1

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.
@@ -35,7 +35,7 @@
35
35
  $(document).ready ->
36
36
  event_rules = new EventRules()
37
37
  # Initialize autocomplete for events
38
- event_rules.cloudfuji_event_autocomplete()
38
+ event_rules.cloudfuji_event_autocomplete() if observed_cloudfuji_events?
39
39
 
40
40
  $("button.add_event_rule").live "click", ->
41
41
  event_rules.add_fields this, $(this).data("content")
@@ -1,3 +1,4 @@
1
1
  /*
2
2
  *= require event_rules
3
+ *= require unknown_emails
3
4
  */
@@ -0,0 +1,10 @@
1
+ table.unknown_emails {
2
+ border-collapse: collapse;
3
+ width: 100%;
4
+ th { text-align: left; }
5
+ td {
6
+ border: 1px solid #ccc;
7
+ padding: 3px;
8
+ }
9
+ }
10
+
@@ -0,0 +1,65 @@
1
+ class UnknownEmailsController < ApplicationController
2
+ before_filter :set_current_tab
3
+
4
+ def index
5
+ # Fetch all emails that don't belong to an
6
+ # entity, and aren't in the 'ignored_emails' table.
7
+ sql = %Q{SELECT * from emails
8
+ WHERE mediator_id IS NULL
9
+ AND NOT EXISTS (
10
+ SELECT DISTINCT(email) FROM ignored_emails
11
+ WHERE email = emails.sent_from
12
+ OR email = emails.sent_to)}
13
+ @unknown_emails = Email.paginate_by_sql(sql, :page => params[:page])
14
+
15
+ respond_with @unknown_emails
16
+ end
17
+
18
+ # Delete email and ignore all emails from this address
19
+ def ignore
20
+ @email = Email.find(params[:id])
21
+ unless address = params[:email]
22
+ if @email.direction == 'received'
23
+ address = @email.sent_from
24
+ elsif @email.direction == 'sent'
25
+ address = @email.sent_to
26
+ end
27
+ end
28
+
29
+ if address.present?
30
+ IgnoredEmail.create :email => address
31
+ @email.destroy
32
+ flash[:notice] = "All emails from #{address} will be ignored."
33
+ else
34
+ flash[:error] = "Could not determine whether this email was sent or received!"
35
+ end
36
+ redirect_to unknown_emails_path
37
+ end
38
+
39
+ # Create lead and attach this email to new lead
40
+ def convert
41
+ address = params[:email]
42
+
43
+ if address.present?
44
+ # Attach all orphaned emails that are from / to address
45
+ @emails = Email.all(:conditions => [%Q{
46
+ mediator_id IS NULL
47
+ AND (emails.sent_from LIKE ?
48
+ OR emails.sent_to LIKE ?)
49
+ }, "%#{address}%", "%#{address}%"])
50
+
51
+ lead = Lead.create :email => address,
52
+ :first_name => address.split("@").first,
53
+ :last_name => address.split("@").last,
54
+ :user => current_user,
55
+ :emails => @emails
56
+
57
+ link_to_lead = ActionController::Base.helpers.link_to(lead_url(lead), lead_url(lead))
58
+ flash[:notice] = "Created lead and attached email(s): #{link_to_lead}".html_safe
59
+ else
60
+ flash[:error] = "Must provide :email param!"
61
+ end
62
+ redirect_to unknown_emails_path
63
+
64
+ end
65
+ end
@@ -0,0 +1,2 @@
1
+ module UnknownEmailsHelper
2
+ end
@@ -24,7 +24,7 @@ class EventRule < ActiveRecord::Base
24
24
  # Don't apply this rule more than limit_per_lead, if set
25
25
  unless limit_per_lead.present? && count.count > limit_per_lead
26
26
  # If :match is present, only apply the rule if data matches string
27
- if match.blank? || (params['data'] && event_matches?(params))
27
+ if match.blank? || event_matches?(params)
28
28
  if (app_id.blank? && page_name.blank?) || page_and_app_matches?(params)
29
29
  # Run the action method if defined
30
30
  if respond_to?(action)
@@ -57,7 +57,7 @@ class EventRule < ActiveRecord::Base
57
57
  when 'cloudfuji_event_received'
58
58
  "Cloudfuji event was received - '#{cloudfuji_event}'"
59
59
  when 'lead_attribute_changed'
60
- "Lead \"#{lead.full_name}\" was updated - #{lead_attribute} was changed from '#{match_data[0]}' to '#{match_data[1]}'."
60
+ "Lead \"#{lead.full_name}\" was updated - #{lead_attribute} was changed from '#{match_data['old_value']}' to '#{match_data['new_value']}'."
61
61
  end
62
62
 
63
63
  User.all.each do |user|
@@ -109,7 +109,7 @@ class EventRule < ActiveRecord::Base
109
109
  match_string.downcase! if case_insensitive_matching
110
110
  match_string.include?(test_string)
111
111
  when 'lead_attribute_changed'
112
- match_string = params[1].to_s.dup
112
+ match_string = params['new_value'].to_s.dup
113
113
  match_string.downcase! if case_insensitive_matching
114
114
  match_string == test_string.to_s
115
115
  end
@@ -0,0 +1,2 @@
1
+ class IgnoredEmail < ActiveRecord::Base
2
+ end
@@ -21,7 +21,8 @@ class CloudfujiLeadObserver < ActiveRecord::Observer
21
21
  def after_update(lead)
22
22
  # Find all event rules where the lead attribute is one of the changed fields
23
23
  EventRule.find_all_by_event_category_and_lead_attribute('lead_attribute_changed', lead.changes.keys).each do |rule|
24
- rule.process(lead, lead.changes[rule.lead_attribute]) # Send [old, new] values as matching data
24
+ old, new = lead.changes[rule.lead_attribute]
25
+ rule.process(lead, {'old_value' => old, 'new_value' => new}) # Send [old, new] values as matching data
25
26
  end
26
27
  end
27
28
  end
@@ -0,0 +1,14 @@
1
+ %tr.highlight[unknown_email]
2
+ - addresses = (unknown_email.direction == 'received' ? unknown_email.sent_from : unknown_email.sent_to).split(";")
3
+ %td= unknown_email.direction.to_s.capitalize
4
+ %td= unknown_email.sent_from
5
+ %td= unknown_email.sent_to
6
+ %td= truncate(unknown_email.subject, :length => 150)
7
+ %td= truncate(unknown_email.body, :length => 150)
8
+ %td
9
+ - addresses.each do |address|
10
+ = address
11
+ %p
12
+ = link_to "Convert to Lead?", convert_unknown_email_path(unknown_email, :email => address), :method => :put
13
+ or
14
+ = link_to "Ignore?", ignore_unknown_email_path(unknown_email, :email => address), :method => :delete
@@ -0,0 +1,22 @@
1
+ = styles_for :unknown_emails
2
+
3
+ .title
4
+ %span#unknown_emails_title Unknown Emails
5
+
6
+ .list
7
+ - if @unknown_emails.any?
8
+ %table.unknown_emails
9
+ %thead
10
+ %tr
11
+ %th Direction
12
+ %th From
13
+ %th To
14
+ %th Subject
15
+ %th Body
16
+ %th Actions
17
+ %tbody#unknown_emails
18
+ = render :partial => 'unknown_email', :collection => @unknown_emails
19
+ - else
20
+ Could not find any emails for unknown leads.
21
+
22
+ #paginate= render "shared/paginate"
@@ -0,0 +1,6 @@
1
+ if @unknown_emails.any?
2
+ page[:unknown_emails].replace_html render(:partial => "unknown_email", :collection => @unknown_emails)
3
+ else
4
+ page[:unknown_emails].replace_html render(:text => "Could not find any emails for unknown leads.")
5
+ end
6
+ page[:paginate].replace_html render(:partial => "shared/paginate")
@@ -20,4 +20,11 @@ Rails.application.routes.draw do
20
20
  post :update, :on => :collection
21
21
  end
22
22
  end
23
+
24
+ resources :unknown_emails, :only => :index do
25
+ member do
26
+ delete :ignore
27
+ put :convert
28
+ end
29
+ end
23
30
  end
@@ -0,0 +1,7 @@
1
+ class CreateIgnoredEmails < ActiveRecord::Migration
2
+ def change
3
+ create_table :ignored_emails do |t|
4
+ t.string :email
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ class AddExtraEmailFields < ActiveRecord::Migration
2
+ def change
3
+ add_column :emails, :direction, :string
4
+ add_column :emails, :imap_folder, :string
5
+ end
6
+ end
@@ -4,6 +4,7 @@ module FatFreeCRM
4
4
  def enable_cloudfuji!
5
5
  load_observers!
6
6
  extend_lead!
7
+ extend_email!
7
8
  # Prevent User class from loading if database is empty
8
9
  if (User.table_exists? rescue false)
9
10
  extend_user!
@@ -44,6 +45,24 @@ module FatFreeCRM
44
45
  end
45
46
  end
46
47
 
48
+ def extend_email!
49
+ Email.class_eval do
50
+ # Sent or received
51
+ def direction
52
+ attr_direction = super
53
+ return attr_direction if attr_direction.present?
54
+
55
+ # If direction not stored, try to deduce
56
+ # from from/to email addresses.
57
+ if sent_from.include?(user.email)
58
+ 'sent'
59
+ elsif sent_to.include?(user.email)
60
+ 'received'
61
+ end
62
+ end
63
+ end
64
+ end
65
+
47
66
  def load_observers!
48
67
  require File.expand_path("../cloudfuji/event_observers/base", __FILE__)
49
68
  Dir[File.expand_path("../cloudfuji/event_observers/*.rb", __FILE__)].each { |file| require file }
@@ -1,3 +1,5 @@
1
+ require 'fat_free_crm/mail_processor/base'
2
+
1
3
  module FatFreeCRM
2
4
  module Cloudfuji
3
5
  module EventObservers
@@ -57,6 +59,31 @@ module FatFreeCRM
57
59
  note_email_activity("#{email} subscribed to a mailing list")
58
60
  end
59
61
 
62
+ def email_received
63
+ user = find_user_by_account
64
+ return unless user
65
+ lead = Lead.find_by_email(data['from'])
66
+ create_email_from_data(
67
+ :direction => 'received',
68
+ :mediator => lead,
69
+ :user => user
70
+ )
71
+ end
72
+
73
+ def email_sent
74
+ user = find_user_by_account
75
+ return unless user
76
+ # Find first Lead from 'to' email addresses
77
+ lead = data['to'].to_s.split(";").detect do |email|
78
+ lead = Lead.find_by_email(email)
79
+ end
80
+ create_email_from_data(
81
+ :direction => 'sent',
82
+ :mediator => lead,
83
+ :user => user
84
+ )
85
+ end
86
+
60
87
  private
61
88
 
62
89
  def note_email_activity(message)
@@ -86,6 +113,32 @@ module FatFreeCRM
86
113
  campaign
87
114
  end
88
115
 
116
+ def find_user_by_account
117
+ user = User.find_by_email(data['account'])
118
+ puts "No User found by email #{data['account']}" unless user
119
+ user
120
+ end
121
+
122
+ def create_email_from_data(options)
123
+ mail = Mail.new(data['rfc822'])
124
+ text_body = FatFreeCRM::MailProcessor::Base.new.send(:plain_text_body, mail)
125
+
126
+ # Remove ID hashes from emails (e.g. ...+23423fce32d@...)
127
+ # This is important so that addresses like
128
+ # reply+****@reply.github.com can be ignored.
129
+ to_address = data['to'].gsub(/\+[^@]+/, '')
130
+ from_address = data['from'].gsub(/\+[^@]+/, '')
131
+
132
+ Email.create({
133
+ :imap_message_id => data['uid'],
134
+ :sent_from => from_address,
135
+ :sent_to => to_address,
136
+ :cc => data['cc'],
137
+ :subject => data['subject'],
138
+ :body => text_body,
139
+ :sent_at => data['date']
140
+ }.merge(options))
141
+ end
89
142
  end
90
143
  end
91
144
  end
@@ -13,9 +13,16 @@ module FatFreeCRM
13
13
  begin
14
14
  unless FatFreeCRM::Tabs.admin.any? {|t| t[:text] == "Event Rules" }
15
15
  FatFreeCRM::Tabs.admin << {
16
- :text => "Event Rules",
17
- :url => { :controller => "admin/event_rules" }
18
- }
16
+ :text => "Event Rules",
17
+ :url => { :controller => "admin/event_rules" }
18
+ }
19
+ end
20
+
21
+ unless FatFreeCRM::Tabs.main.any? {|t| t[:text] == "Unknown Emails" }
22
+ FatFreeCRM::Tabs.main << {
23
+ :text => "Unknown Emails",
24
+ :url => { :controller => "unknown_emails" }
25
+ }
19
26
  end
20
27
  rescue TypeError
21
28
  puts "You must migrate your settings table."
@@ -1,5 +1,5 @@
1
1
  module FatFreeCRM
2
2
  module Cloudfuji
3
- VERSION = '0.3.1'
3
+ VERSION = '0.4.1'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffcrm_cloudfuji
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-06-07 00:00:00.000000000 Z
13
+ date: 2012-06-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec-rails
@@ -108,9 +108,13 @@ files:
108
108
  - app/assets/javascripts/ffcrm_cloudfuji.js
109
109
  - app/assets/stylesheets/event_rules.css.scss
110
110
  - app/assets/stylesheets/ffcrm_cloudfuji.css
111
+ - app/assets/stylesheets/unknown_emails.css.scss
111
112
  - app/controllers/admin/event_rules_controller.rb
113
+ - app/controllers/unknown_emails_controller.rb
112
114
  - app/helpers/admin/event_rules_helper.rb
115
+ - app/helpers/unknown_emails_helper.rb
113
116
  - app/models/event_rule.rb
117
+ - app/models/ignored_email.rb
114
118
  - app/models/lead_event_rule_count.rb
115
119
  - app/observers/cloudfuji_lead_observer.rb
116
120
  - app/views/admin/event_rules/_errors.html.haml
@@ -119,6 +123,9 @@ files:
119
123
  - app/views/leads/_lead.html.haml
120
124
  - app/views/leads/_sidebar_show_lead_scoring.html.haml
121
125
  - app/views/leads/_top_section_ido_id.html.haml
126
+ - app/views/unknown_emails/_unknown_email.html.haml
127
+ - app/views/unknown_emails/index.html.haml
128
+ - app/views/unknown_emails/index.js.rjs
122
129
  - config.ru
123
130
  - config/database.yml
124
131
  - config/initializers/cloudfuji.rb
@@ -130,6 +137,8 @@ files:
130
137
  - db/migrate/20120524031157_extend_lead_scoring_as_event_rules.rb
131
138
  - db/migrate/20120525151511_add_ido_id_to_lead.rb
132
139
  - db/migrate/20120607115701_add_mailing_list_and_page_fields_to_event_rules.rb
140
+ - db/migrate/20120612140812_create_ignored_emails.rb
141
+ - db/migrate/20120612200812_add_extra_email_fields.rb
133
142
  - ffcrm_cloudfuji.gemspec
134
143
  - install.rb
135
144
  - lib/fat_free_crm/cloudfuji.rb
@@ -169,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
178
  version: '0'
170
179
  segments:
171
180
  - 0
172
- hash: 1944626669401206856
181
+ hash: 2361827458429134483
173
182
  required_rubygems_version: !ruby/object:Gem::Requirement
174
183
  none: false
175
184
  requirements:
@@ -178,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
178
187
  version: '0'
179
188
  segments:
180
189
  - 0
181
- hash: 1944626669401206856
190
+ hash: 2361827458429134483
182
191
  requirements: []
183
192
  rubyforge_project:
184
193
  rubygems_version: 1.8.24