ffcrm_cloudfuji 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/app/assets/javascripts/event_rules.js.coffee +55 -0
  2. data/app/assets/javascripts/ffcrm_cloudfuji.js +1 -1
  3. data/app/assets/stylesheets/event_rules.css.scss +53 -0
  4. data/app/assets/stylesheets/ffcrm_cloudfuji.css +1 -1
  5. data/app/controllers/admin/{lead_scoring_controller.rb → event_rules_controller.rb} +12 -12
  6. data/app/helpers/admin/event_rules_helper.rb +47 -0
  7. data/app/models/event_rule.rb +112 -0
  8. data/app/models/lead_event_rule_count.rb +4 -0
  9. data/app/observers/cloudfuji_lead_observer.rb +27 -0
  10. data/app/views/admin/{lead_scoring → event_rules}/_errors.html.haml +1 -1
  11. data/app/views/admin/event_rules/_form.html.haml +39 -0
  12. data/app/views/admin/{lead_scoring → event_rules}/index.html.haml +7 -7
  13. data/app/views/leads/_sidebar_show_lead_scoring.html.haml +3 -3
  14. data/config/locales/en-US.yml +5 -0
  15. data/config/routes.rb +1 -1
  16. data/db/migrate/20120524031157_extend_lead_scoring_as_event_rules.rb +54 -0
  17. data/db/migrate/20120525151511_add_ido_id_to_lead.rb +5 -0
  18. data/lib/fat_free_crm/cloudfuji/event_observers/customer_observer.rb +3 -1
  19. data/lib/fat_free_crm/cloudfuji/event_observers/email_observer.rb +4 -2
  20. data/lib/fat_free_crm/cloudfuji/event_observers/event_rules_observer.rb +23 -0
  21. data/lib/fat_free_crm/cloudfuji/event_observers/user_observer.rb +6 -5
  22. data/lib/fat_free_crm/cloudfuji.rb +1 -1
  23. data/lib/ffcrm_cloudfuji/engine.rb +9 -4
  24. data/lib/ffcrm_cloudfuji/version.rb +1 -1
  25. data/spec/event_observers/event_rules_observer_spec.rb +103 -0
  26. data/spec/factories/lead_scoring_factories.rb +9 -3
  27. data/spec/internal/db/schema.rb +19 -13
  28. data/spec/models/event_rule_spec.rb +47 -0
  29. data/spec/observers/cloudfuji_lead_observer_spec.rb +26 -0
  30. metadata +80 -92
  31. data/app/assets/javascripts/lead_scoring.js.coffee +0 -42
  32. data/app/assets/stylesheets/lead_scoring.css.scss +0 -47
  33. data/app/helpers/admin/lead_scoring_helper.rb +0 -10
  34. data/app/models/lead_scoring_rule.rb +0 -6
  35. data/app/models/lead_scoring_rule_count.rb +0 -4
  36. data/app/views/admin/lead_scoring/_form.html.haml +0 -14
  37. data/config/initializers/inflections.rb +0 -3
  38. data/lib/fat_free_crm/cloudfuji/event_observers/lead_scoring_observer.rb +0 -38
  39. data/spec/event_observers/lead_scoring_observer_spec.rb +0 -87
@@ -0,0 +1,55 @@
1
+ (($) ->
2
+ class @EventRules
3
+ constructor: (@templates = {}) ->
4
+
5
+ add_fields: (button, content) ->
6
+ new_id = new Date().getTime()
7
+ regexp = new RegExp('new_event_rule', 'g')
8
+ $('ul#event_rules').append(content.replace(regexp, new_id))
9
+ # Setup event autocomplete for new field
10
+ this.cloudfuji_event_autocomplete('input#event_rules_'+new_id+'_cloudfuji_event')
11
+
12
+ remove_fields: (button) ->
13
+ container = $(button).closest('li.event_rule')
14
+ index = container.data('index')
15
+ # If rule has no id, just remove
16
+ if $("#event_rules_"+index+"_id").length == 0
17
+ container.remove()
18
+ else
19
+ # If rule has an id, mark container as hidden and add _destroy field
20
+ container.hide()
21
+ container.append($('<input type="text" name="event_rules['+index+'][_destroy]" value="yes">'))
22
+
23
+ cloudfuji_event_autocomplete: (selector = 'input.cloudfuji_event') ->
24
+ $(selector).autocomplete({source: observed_cloudfuji_events, minLength: 0})
25
+ # Show all events on focus, if input is empty
26
+ $(selector).focus ->
27
+ $(this).autocomplete "search", "" if $(this).val() == ""
28
+
29
+ show_field_group: (select, group_name, key) ->
30
+ # Hide all fields, then show the selected field group
31
+ container = $(select).closest('li.event_rule')
32
+ container.find('.'+group_name+'_fields').hide()
33
+ container.find('.'+group_name+'_'+key).show()
34
+
35
+ $(document).ready ->
36
+ event_rules = new EventRules()
37
+ # Initialize autocomplete for events
38
+ event_rules.cloudfuji_event_autocomplete()
39
+
40
+ $("button.add_event_rule").live "click", ->
41
+ event_rules.add_fields this, $(this).data("content")
42
+ false
43
+
44
+ $(".remove_event_rule").live "click", ->
45
+ event_rules.remove_fields this
46
+ false
47
+
48
+ $('.event_category_select').live "change", ->
49
+ event_rules.show_field_group this, 'event_category', $(this).val()
50
+
51
+ $('.action_select').live "change", ->
52
+ event_rules.show_field_group this, 'action', $(this).val()
53
+
54
+
55
+ ) jQuery
@@ -1 +1 @@
1
- //= require lead_scoring
1
+ //= require event_rules
@@ -0,0 +1,53 @@
1
+ ul#event_rules {
2
+ div { display: inline; }
3
+
4
+ li.event_rule {
5
+ font-size: 13px;
6
+
7
+ &:last-child {
8
+ border-bottom: none;
9
+ }
10
+
11
+ input {
12
+ font-size: 13px;
13
+ margin: 0 4px;
14
+ vertical-align: middle;
15
+ margin-bottom: 3px;
16
+ }
17
+ .cloudfuji_event { width: 120px; }
18
+ .match_input { width: 140px; }
19
+ .numeric_input { width: 35px; }
20
+ .tag_input { width: 100px; }
21
+ input[type='checkbox'] {
22
+ width: 14px;
23
+ margin-left: 2px;
24
+ }
25
+
26
+ .field_with_errors {
27
+ display: inline;
28
+ input, select {
29
+ background-color: #ffdddd;
30
+ }
31
+ select {
32
+ border: 2px solid #ff9999;
33
+ }
34
+ }
35
+ }
36
+
37
+ a.remove_event_rule {
38
+ margin-right: 6px;
39
+ img {
40
+ vertical-align: middle;
41
+ margin-bottom: 4px;
42
+ }
43
+ }
44
+ }
45
+
46
+ .buttonbar.event_rules_buttons {
47
+ width: 1155px;
48
+ float: left;
49
+ font-size: 13px;
50
+ input[type='submit'], button { font-size: 14px; }
51
+ .save_or_cancel { float: right; }
52
+ button { float: left; }
53
+ }
@@ -1,3 +1,3 @@
1
1
  /*
2
- *= require lead_scoring
2
+ *= require event_rules
3
3
  */
@@ -1,41 +1,41 @@
1
- class Admin::LeadScoringController < Admin::ApplicationController
1
+ class Admin::EventRulesController < Admin::ApplicationController
2
2
  before_filter :require_user
3
- before_filter "set_current_tab('admin/lead_scoring')", :only => [ :index, :update ]
3
+ before_filter "set_current_tab('admin/event_rules')", :only => [ :index, :update ]
4
4
 
5
- # GET /admin/lead_scoring
5
+ # GET /admin/event_rules
6
6
  #----------------------------------------------------------------------------
7
7
  def index
8
- @lead_scoring_rules = LeadScoringRule.all
9
- @lead_scoring_rules << LeadScoringRule.new if @lead_scoring_rules.empty?
8
+ @event_rules = EventRule.all
9
+ @event_rules << EventRule.new if @event_rules.empty?
10
10
 
11
11
  respond_to do |format|
12
12
  format.html # index.html.haml
13
13
  end
14
14
  end
15
15
 
16
- # PUT /admin/lead_scoring
16
+ # PUT /admin/event_rules
17
17
  #----------------------------------------------------------------------------
18
18
  def update
19
19
  # Create rules without ids,
20
20
  # destroy rules with '_destroy' param,
21
21
  # update rules with ids
22
- @lead_scoring_rules = []
23
- params[:lead_scoring_rules].each do |index, data|
22
+ @event_rules = []
23
+ params[:event_rules].each do |index, data|
24
24
  if data["id"].blank?
25
- @lead_scoring_rules << LeadScoringRule.create(data)
25
+ @event_rules << EventRule.create(data)
26
26
  else
27
- if rule = LeadScoringRule.find_by_id(data["id"])
27
+ if rule = EventRule.find_by_id(data["id"])
28
28
  if data["_destroy"]
29
29
  rule.destroy
30
30
  else
31
31
  rule.update_attributes data
32
- @lead_scoring_rules << rule
32
+ @event_rules << rule
33
33
  end
34
34
  end
35
35
  end
36
36
  end
37
37
 
38
- if @lead_scoring_rules.all?(&:valid?)
38
+ if @event_rules.all?(&:valid?)
39
39
  flash[:notice] = "All rules were saved successfully."
40
40
  else
41
41
  flash[:error] = render_to_string(:partial => "errors").html_safe
@@ -0,0 +1,47 @@
1
+ module Admin::EventRulesHelper
2
+
3
+ def add_event_rule_button(f)
4
+ fields = f.fields_for "new_event_rule", EventRule.new do |builder|
5
+ render("form", :r => builder, :index => "new_event_rule")
6
+ end
7
+ button_tag 'Add New Rule', :class => "add_event_rule", "data-content" => "#{fields}"
8
+ end
9
+
10
+ def event_category_select(form)
11
+ form.select :event_category, [
12
+ ["Cloudfuji event", :cloudfuji_event_received],
13
+ ["Lead attribute", :lead_attribute_changed]
14
+ ], {}, :class => "event_category_select"
15
+ end
16
+
17
+ def action_select(form)
18
+ form.select :action, [
19
+ ["change Lead score", :change_lead_score],
20
+ ["send notification", :send_notification],
21
+ ["add tag", :add_tag],
22
+ ["remove tag", :remove_tag]
23
+ ], {}, :class => "action_select"
24
+ end
25
+
26
+ # Generates divs with form field groups for event rules
27
+ def fields_for_event_rule_group(object, subjects, field)
28
+ subjects = [subjects].flatten
29
+ content_tag(:div, :class => subjects.map {|s| "#{field}_#{s}" }.join(" ") << " #{field}_fields",
30
+ :style => (subjects.none? {|s| s == object.send(field) } ? "display: none;" : "")) do
31
+ yield
32
+ end
33
+ end
34
+
35
+ def event_fields_for(object, events, &content)
36
+ fields_for_event_rule_group(object, events, 'event_category', &content)
37
+ end
38
+
39
+ def action_fields_for(object, actions, &content)
40
+ fields_for_event_rule_group(object, actions, 'action', &content)
41
+ end
42
+
43
+ def lead_attributes
44
+ Lead.attribute_names - %w(id deleted_at updated_at created_at)
45
+ end
46
+
47
+ end
@@ -0,0 +1,112 @@
1
+ class EventRule < ActiveRecord::Base
2
+
3
+ # event category validations
4
+ validates_presence_of :event_category
5
+ validates_presence_of :cloudfuji_event, :if => lambda { self.event_category == 'cloudfuji_event_received' }
6
+ validates_presence_of :lead_attribute, :if => lambda { self.event_category == 'lead_attribute_changed' }
7
+
8
+ # action validations
9
+ validates_presence_of :action
10
+ validates_presence_of :tag, :if => lambda { %w(add_tag remove_tag).include?(self.action) }
11
+ validates_numericality_of :change_score_by, :only_integer => true, :if => lambda { self.action == 'change_lead_score' }
12
+
13
+ validates_numericality_of :limit_per_lead, :only_integer => true, :allow_blank => true
14
+
15
+ has_many :lead_event_rule_counts
16
+
17
+ def process(lead, match_data)
18
+ # How many times this rule has been applied to a given Lead
19
+ count = LeadEventRuleCount.find_by_lead_id_and_event_rule_id(lead, self) ||
20
+ LeadEventRuleCount.new(:lead => lead, :event_rule => self)
21
+ # Don't apply this rule more than limit_per_lead, if set
22
+ unless limit_per_lead.present? && count.count > limit_per_lead
23
+ # If :match is present, only apply the rule if data matches string
24
+ if match.blank? || event_matches?(match_data)
25
+ # Run the action method if defined
26
+ if respond_to?(action)
27
+ send(action, lead, match_data)
28
+ # Increment and save count of rule/lead applications
29
+ count.count += 1
30
+ count.save
31
+ else
32
+ raise "Do not know how to process '#{action}' action."
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ # Actions
39
+ # -----------------------------------------------------------------
40
+ def change_lead_score(lead, match_data)
41
+ lead.without_versioning do
42
+ lead.update_attribute :score, lead.score + change_score_by
43
+ end
44
+ # Add history event to lead, to record change of score
45
+ lead.versions.create! :event => "Rule for #{human_event_label}: Score changed by #{change_score_by} points. (New total: #{lead.score})"
46
+ end
47
+
48
+ def send_notification(lead, match_data)
49
+ if ::Cloudfuji::Platform.on_cloudfuji?
50
+ # Fire a Cloudfuji event
51
+ message = case event_category
52
+ when 'cloudfuji_event_received'
53
+ "Cloudfuji event was received - '#{cloudfuji_event}'"
54
+ when 'lead_attribute_changed'
55
+ "Lead \"#{lead.full_name}\" was updated - #{lead_attribute} was changed from '#{match_data[0]}' to '#{match_data[1]}'."
56
+ end
57
+
58
+ event = {
59
+ :category => :fat_free_crm,
60
+ :name => :notification,
61
+ :data => {
62
+ :message => message
63
+ }
64
+ }
65
+ ::Cloudfuji::Event.publish(event)
66
+ end
67
+ end
68
+
69
+ def add_tag(lead, match_data)
70
+ lead.tag_list << tag
71
+ save_lead_without_versioning_or_observers(lead)
72
+ lead.versions.create! :event => "Rule for #{human_event_label}: Added tag '#{tag}'"
73
+ end
74
+
75
+ def remove_tag(lead, match_data)
76
+ lead.tag_list -= [tag]
77
+ save_lead_without_versioning_or_observers(lead)
78
+ lead.versions.create! :event => "Rule for #{human_event_label}: Removed tag '#{tag}'"
79
+ end
80
+
81
+
82
+ private
83
+
84
+ def event_matches?(match_data)
85
+ test_string = case_insensitive_matching ? match.downcase : match
86
+ case event_category
87
+ when 'cloudfuji_event_received'
88
+ match_string = match_data.inspect
89
+ match_string.downcase! if case_insensitive_matching
90
+ match_string.include?(test_string)
91
+ when 'lead_attribute_changed'
92
+ match_string = match_data[1].dup
93
+ match_string.downcase! if case_insensitive_matching
94
+ match_string == test_string
95
+ end
96
+ end
97
+
98
+ def human_event_label
99
+ case event_category
100
+ when 'cloudfuji_event_received'; "Cloudfuji event - '#{cloudfuji_event}'"
101
+ when 'lead_attribute_changed'; "Lead update - '#{lead_attribute}'"
102
+ end
103
+ end
104
+
105
+ def save_lead_without_versioning_or_observers(lead)
106
+ Lead.observers.disable :cloudfuji_lead_observer do
107
+ lead.without_versioning do
108
+ lead.save
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,4 @@
1
+ class LeadEventRuleCount < ActiveRecord::Base
2
+ belongs_to :lead
3
+ belongs_to :event_rule
4
+ end
@@ -0,0 +1,27 @@
1
+ # Fat Free CRM
2
+ # Copyright (C) 2008-2011 by Michael Dvorkin
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #------------------------------------------------------------------------------
17
+
18
+ class CloudfujiLeadObserver < ActiveRecord::Observer
19
+ observe :lead
20
+
21
+ def after_update(lead)
22
+ # Find all event rules where the lead attribute is one of the changed fields
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
25
+ end
26
+ end
27
+ end
@@ -1,4 +1,4 @@
1
- - invalid_rules = @lead_scoring_rules.select{|r| r.errors.any? }
1
+ - invalid_rules = @event_rules.select{|r| r.errors.any? }
2
2
  - if invalid_rules.any?
3
3
  There were (#{invalid_rules.size}) invalid rules:
4
4
  %br
@@ -0,0 +1,39 @@
1
+ %li.event_rule{"data-index" => index}
2
+ = link_to image_tag('delete.png', :size => '16x16', :alt => 'Remove Rule'), nil, :class => "remove_event_rule"
3
+
4
+ = r.hidden_field(:id) unless r.object.new_record?
5
+
6
+ If
7
+ = event_category_select(r)
8
+
9
+ = event_fields_for(r.object, 'cloudfuji_event_received') do
10
+ = r.text_field :cloudfuji_event, :class => "cloudfuji_event"
11
+ is received, and contains
12
+
13
+ = event_fields_for(r.object, 'lead_attribute_changed') do
14
+ = r.select :lead_attribute, lead_attributes, :class => "lead_attribute", :include_blank => true
15
+ changes, and equals
16
+
17
+ = content_tag(:small, "(optional)") << ":".html_safe
18
+ = r.text_field :match, :class => "match_input"
19
+
20
+ %small
21
+ (Case insensitive?
22
+ = r.check_box(:case_insensitive_matching) << h(")")
23
+
24
+ then
25
+ = action_select(r)
26
+
27
+ = action_fields_for(r.object, 'change_lead_score') do
28
+ by
29
+ = r.text_field :change_score_by, :class => "numeric_input"
30
+ points.
31
+
32
+ -# Add/Remove tag actions share the same field
33
+ = action_fields_for(r.object, %w(add_tag remove_tag)) do
34
+ = r.text_field :tag, :class => "tag_input"
35
+
36
+ = action_fields_for(r.object, %w(change_lead_score send_notification)) do
37
+ %small
38
+ (Limit per lead:
39
+ = r.text_field(:limit_per_lead, :class => "numeric_input") << h(")")
@@ -2,18 +2,18 @@
2
2
  var observed_cloudfuji_events = #{Cloudfuji::Data.observed_events.map(&:to_s).inspect};
3
3
 
4
4
  .title
5
- Lead Scoring
5
+ Event Rules
6
6
 
7
7
  .list
8
- = form_for :lead_scoring_rules do |f|
9
- %ul#lead_scoring_rules
10
- - @lead_scoring_rules.each_with_index do |rule, i|
8
+ = form_for :event_rules do |f|
9
+ %ul#event_rules
10
+ - @event_rules.each_with_index do |rule, i|
11
11
  = f.fields_for i.to_s, rule do |r|
12
12
  = render "form", :r => r, :index => i
13
13
 
14
- .buttonbar.lead_scoring_buttons
15
- = add_lead_scoring_rule_button(f)
14
+ .buttonbar.event_rules_buttons
15
+ = add_event_rule_button(f)
16
16
  .save_or_cancel
17
17
  = submit_tag 'Save', :name => :save
18
18
  #{t :or}
19
- = link_to "Cancel", admin_lead_scoring_index_path
19
+ = link_to "Cancel", admin_event_rules_path
@@ -1,8 +1,8 @@
1
- .caption Lead Scoring
1
+ .caption Event Rules
2
2
  %li
3
3
  %dt= lead.score
4
4
  %tt Score:
5
- - if lead.respond_to?(:lead_scoring_rule_counts) && lead.lead_scoring_rule_counts.any?
5
+ - if lead.respond_to?(:lead_event_rule_counts) && lead.lead_event_rule_counts.any?
6
6
  %li
7
- %dt= lead.lead_scoring_rule_counts.sum {|c| c.count }
7
+ %dt= lead.lead_event_rule_counts.sum {|c| c.count }
8
8
  %tt Total scoring events:
@@ -0,0 +1,5 @@
1
+ "en-US":
2
+ activerecord:
3
+ attributes:
4
+ event_rule:
5
+ change_score_by: "Points"
data/config/routes.rb CHANGED
@@ -16,7 +16,7 @@ Rails.application.routes.draw do
16
16
  end
17
17
 
18
18
  namespace :admin do
19
- resources :lead_scoring, :only => :index do
19
+ resources :event_rules, :only => :index do
20
20
  post :update, :on => :collection
21
21
  end
22
22
  end
@@ -0,0 +1,54 @@
1
+ class ExtendLeadScoringAsEventRules < ActiveRecord::Migration
2
+ def up
3
+ # Save current values of boolean :once column
4
+ once_values = connection.select_all("SELECT id,once from lead_scoring_rules;")
5
+
6
+ rename_table :lead_scoring_rules, :event_rules
7
+
8
+ rename_table :lead_scoring_rule_counts, :lead_event_rule_counts
9
+ rename_column :lead_event_rule_counts, :lead_scoring_rule_id, :event_rule_id
10
+
11
+ add_column :event_rules, :event_category, :string, :default => 'cloudfuji_event_received'
12
+
13
+ # Columns for cloudfuji event matching
14
+ rename_column :event_rules, :event, :cloudfuji_event
15
+
16
+ # Columns for lead column changes
17
+ add_column :event_rules, :lead_attribute, :string
18
+
19
+ # Columns for actions
20
+ add_column :event_rules, :action, :string, :default => 'change_lead_score'
21
+ add_column :event_rules, :tag, :string
22
+ rename_column :event_rules, :points, :change_score_by
23
+
24
+ remove_column :event_rules, :once
25
+ add_column :event_rules, :limit_per_lead, :integer
26
+ add_column :event_rules, :case_insensitive_matching, :boolean
27
+
28
+ # Migrate :once values to :limit_times & :max_times
29
+ ids = once_values.select{|v| v['once'] == 't' }.map {|v| v['id'] }
30
+ if ids.any?
31
+ connection.execute("UPDATE event_rules SET limit_times = 1, max_times = 1 WHERE id IN (#{ids.join(',')});")
32
+ end
33
+
34
+ end
35
+
36
+ # Instead of meticulously mirroring the reverse of all these changes,
37
+ # just drop the tables and re-create the tables from the previous migration.
38
+ def down
39
+ # Remove tables
40
+ drop_table :event_rules
41
+ drop_table :lead_event_rule_counts
42
+ # Load previous migration
43
+ require File.expand_path('../20120515194445_add_lead_scoring_rules.rb', __FILE__)
44
+ migration = AddLeadScoringRules.new
45
+ # Only create tables (don't re-add columns to app tables)
46
+ migration.class_eval do
47
+ def add_column(table, column, type, options)
48
+ puts "-- not re-adding '#{column}' column to '#{table}' table."
49
+ end
50
+ end
51
+ # Run migration
52
+ migration.up
53
+ end
54
+ end
@@ -0,0 +1,5 @@
1
+ class AddIdoIdToLead < ActiveRecord::Migration
2
+ def change
3
+ add_column :leads, :ido_id, :text
4
+ end
5
+ end
@@ -42,10 +42,12 @@ module FatFreeCRM
42
42
  return result if result
43
43
  end
44
44
 
45
- lead = Lead.find_by_email(data['email']) || Lead.new
45
+ lead = Lead.find_by_ido_id(data['customer_ido_id'])
46
+ lead ||= Lead.find_by_email(data['email'])
46
47
  lead ||= Lead.new
47
48
 
48
49
  lead.email = data['email']
50
+ lead.ido_id = data['customer_ido_id']
49
51
  lead.first_name = data['first_name'] || data['email'].split("@").first if lead.first_name.blank?
50
52
  lead.last_name = data['last_name'] || data['email'].split("@").last if lead.last_name.blank?
51
53
  lead.user ||= User.first
@@ -79,10 +79,12 @@ module FatFreeCRM
79
79
  end
80
80
 
81
81
  puts "No pre-existing records found, creating a lead"
82
- lead = Lead.find_by_email(recipient)
82
+ lead = Lead.find_by_ido_id(data['customer_ido_id'])
83
+ lead ||= Lead.find_by_email(recipient)
83
84
  lead ||= Lead.new
84
85
 
85
- lead.email = recipient
86
+ lead.email = recipient
87
+ lead.ido_id = data['customer_ido_id']
86
88
  lead.first_name = recipient.split("@").first if lead.first_name.blank?
87
89
  lead.last_name = recipient.split("@").last if lead.last_name.blank?
88
90
  lead.user ||= User.first
@@ -0,0 +1,23 @@
1
+ module FatFreeCRM
2
+ module Cloudfuji
3
+ module EventObservers
4
+ class EventRulesObserver < ::Cloudfuji::EventObserver
5
+ # Fire for all events
6
+ def catch_all
7
+ data = params['data']
8
+ email = data['email'] || data['recipient']
9
+ # Look up Lead by ido_id, fall back to email address
10
+ lead = Lead.find_by_ido_id(data['customer_ido_id'])
11
+ if lead ||= Lead.find_by_email(email)
12
+ event_name = "#{params['category']}_#{params['event']}"
13
+
14
+ EventRule.find_all_by_event_category_and_cloudfuji_event('cloudfuji_event_received', event_name).each do |rule|
15
+ rule.process(lead, params['data'])
16
+ end
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -3,20 +3,21 @@ module FatFreeCRM
3
3
  module EventObservers
4
4
  class UserObserver < ::Cloudfuji::EventObserver
5
5
  def user_added
6
+ data = params['data']
7
+ ido_id = data['ido_id'].to_s
8
+
6
9
  puts "Adding a new user with incoming data #{params.inspect}"
7
10
  puts "Authlogic username column: #{::Authlogic::Cas.cas_username_column}="
8
- puts "Setting username to: #{params['data'].try(:[], 'ido_id')}"
9
-
10
- data = params['data']
11
+ puts "Setting username to: #{ido_id}"
11
12
 
12
- user = User.unscoped.find_or_create_by_ido_id(data['ido_id'])
13
+ user = User.unscoped.find_or_create_by_ido_id(ido_id)
13
14
 
14
15
  user.email = data['email']
15
16
  user.first_name = user.email.split('@').first
16
17
  user.last_name = user.email.split('@').last
17
18
  user.username = data['email']
18
19
  user.deleted_at = nil
19
- user.send("#{::Authlogic::Cas.cas_username_column}=".to_sym, data.try(:[], 'ido_id'))
20
+ user.send("#{::Authlogic::Cas.cas_username_column}=".to_sym, ido_id)
20
21
 
21
22
  puts user.inspect
22
23
 
@@ -37,7 +37,7 @@ module FatFreeCRM
37
37
  def extend_lead!
38
38
  puts "Extending the Lead model"
39
39
  Lead.instance_eval do
40
- has_many :lead_scoring_rule_counts
40
+ has_many :lead_event_rule_counts
41
41
  end
42
42
  end
43
43
 
@@ -1,15 +1,20 @@
1
1
  module FatFreeCRM
2
2
  module Cloudfuji
3
3
  class Engine < Rails::Engine
4
+ config.before_initialize do
5
+ # Register observers to fire Cloudfuji events
6
+ (config.active_record.observers ||= []) << :cloudfuji_lead_observer
7
+ end
8
+
4
9
  config.to_prepare do
5
10
  require 'fat_free_crm/cloudfuji/view_hooks'
6
11
 
7
- # Add Lead Scoring tab
12
+ # Add Event Rules tab
8
13
  begin
9
- unless FatFreeCRM::Tabs.admin.any? {|t| t[:text] == "Lead Scoring" }
14
+ unless FatFreeCRM::Tabs.admin.any? {|t| t[:text] == "Event Rules" }
10
15
  FatFreeCRM::Tabs.admin << {
11
- :text => "Lead Scoring",
12
- :url => { :controller => "admin/lead_scoring" }
16
+ :text => "Event Rules",
17
+ :url => { :controller => "admin/event_rules" }
13
18
  }
14
19
  end
15
20
  rescue TypeError
@@ -1,5 +1,5 @@
1
1
  module FatFreeCRM
2
2
  module Cloudfuji
3
- VERSION = '0.2.1'
3
+ VERSION = '0.2.2'
4
4
  end
5
5
  end