ffcrm_cloudfuji 0.2.1 → 0.2.2

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.
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