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.
- data/app/assets/javascripts/event_rules.js.coffee +55 -0
- data/app/assets/javascripts/ffcrm_cloudfuji.js +1 -1
- data/app/assets/stylesheets/event_rules.css.scss +53 -0
- data/app/assets/stylesheets/ffcrm_cloudfuji.css +1 -1
- data/app/controllers/admin/{lead_scoring_controller.rb → event_rules_controller.rb} +12 -12
- data/app/helpers/admin/event_rules_helper.rb +47 -0
- data/app/models/event_rule.rb +112 -0
- data/app/models/lead_event_rule_count.rb +4 -0
- data/app/observers/cloudfuji_lead_observer.rb +27 -0
- data/app/views/admin/{lead_scoring → event_rules}/_errors.html.haml +1 -1
- data/app/views/admin/event_rules/_form.html.haml +39 -0
- data/app/views/admin/{lead_scoring → event_rules}/index.html.haml +7 -7
- data/app/views/leads/_sidebar_show_lead_scoring.html.haml +3 -3
- data/config/locales/en-US.yml +5 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20120524031157_extend_lead_scoring_as_event_rules.rb +54 -0
- data/db/migrate/20120525151511_add_ido_id_to_lead.rb +5 -0
- data/lib/fat_free_crm/cloudfuji/event_observers/customer_observer.rb +3 -1
- data/lib/fat_free_crm/cloudfuji/event_observers/email_observer.rb +4 -2
- data/lib/fat_free_crm/cloudfuji/event_observers/event_rules_observer.rb +23 -0
- data/lib/fat_free_crm/cloudfuji/event_observers/user_observer.rb +6 -5
- data/lib/fat_free_crm/cloudfuji.rb +1 -1
- data/lib/ffcrm_cloudfuji/engine.rb +9 -4
- data/lib/ffcrm_cloudfuji/version.rb +1 -1
- data/spec/event_observers/event_rules_observer_spec.rb +103 -0
- data/spec/factories/lead_scoring_factories.rb +9 -3
- data/spec/internal/db/schema.rb +19 -13
- data/spec/models/event_rule_spec.rb +47 -0
- data/spec/observers/cloudfuji_lead_observer_spec.rb +26 -0
- metadata +80 -92
- data/app/assets/javascripts/lead_scoring.js.coffee +0 -42
- data/app/assets/stylesheets/lead_scoring.css.scss +0 -47
- data/app/helpers/admin/lead_scoring_helper.rb +0 -10
- data/app/models/lead_scoring_rule.rb +0 -6
- data/app/models/lead_scoring_rule_count.rb +0 -4
- data/app/views/admin/lead_scoring/_form.html.haml +0 -14
- data/config/initializers/inflections.rb +0 -3
- data/lib/fat_free_crm/cloudfuji/event_observers/lead_scoring_observer.rb +0 -38
- 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
|
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,41 +1,41 @@
|
|
1
|
-
class Admin::
|
1
|
+
class Admin::EventRulesController < Admin::ApplicationController
|
2
2
|
before_filter :require_user
|
3
|
-
before_filter "set_current_tab('admin/
|
3
|
+
before_filter "set_current_tab('admin/event_rules')", :only => [ :index, :update ]
|
4
4
|
|
5
|
-
# GET /admin/
|
5
|
+
# GET /admin/event_rules
|
6
6
|
#----------------------------------------------------------------------------
|
7
7
|
def index
|
8
|
-
@
|
9
|
-
@
|
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/
|
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
|
-
@
|
23
|
-
params[:
|
22
|
+
@event_rules = []
|
23
|
+
params[:event_rules].each do |index, data|
|
24
24
|
if data["id"].blank?
|
25
|
-
@
|
25
|
+
@event_rules << EventRule.create(data)
|
26
26
|
else
|
27
|
-
if rule =
|
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
|
-
@
|
32
|
+
@event_rules << rule
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
if @
|
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,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
|
@@ -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
|
-
|
5
|
+
Event Rules
|
6
6
|
|
7
7
|
.list
|
8
|
-
= form_for :
|
9
|
-
%ul#
|
10
|
-
- @
|
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.
|
15
|
-
=
|
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",
|
19
|
+
= link_to "Cancel", admin_event_rules_path
|
@@ -1,8 +1,8 @@
|
|
1
|
-
.caption
|
1
|
+
.caption Event Rules
|
2
2
|
%li
|
3
3
|
%dt= lead.score
|
4
4
|
%tt Score:
|
5
|
-
- if lead.respond_to?(:
|
5
|
+
- if lead.respond_to?(:lead_event_rule_counts) && lead.lead_event_rule_counts.any?
|
6
6
|
%li
|
7
|
-
%dt= lead.
|
7
|
+
%dt= lead.lead_event_rule_counts.sum {|c| c.count }
|
8
8
|
%tt Total scoring events:
|
data/config/routes.rb
CHANGED
@@ -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
|
@@ -42,10 +42,12 @@ module FatFreeCRM
|
|
42
42
|
return result if result
|
43
43
|
end
|
44
44
|
|
45
|
-
lead
|
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.
|
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
|
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: #{
|
9
|
-
|
10
|
-
data = params['data']
|
11
|
+
puts "Setting username to: #{ido_id}"
|
11
12
|
|
12
|
-
user = User.unscoped.find_or_create_by_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,
|
20
|
+
user.send("#{::Authlogic::Cas.cas_username_column}=".to_sym, ido_id)
|
20
21
|
|
21
22
|
puts user.inspect
|
22
23
|
|
@@ -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
|
12
|
+
# Add Event Rules tab
|
8
13
|
begin
|
9
|
-
unless FatFreeCRM::Tabs.admin.any? {|t| t[:text] == "
|
14
|
+
unless FatFreeCRM::Tabs.admin.any? {|t| t[:text] == "Event Rules" }
|
10
15
|
FatFreeCRM::Tabs.admin << {
|
11
|
-
:text => "
|
12
|
-
:url => { :controller => "admin/
|
16
|
+
:text => "Event Rules",
|
17
|
+
:url => { :controller => "admin/event_rules" }
|
13
18
|
}
|
14
19
|
end
|
15
20
|
rescue TypeError
|