e9_crm 0.1.8 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -3
- data/app/controllers/e9_crm/advertising_campaigns_controller.rb +2 -0
- data/app/controllers/e9_crm/affiliate_campaigns_controller.rb +2 -0
- data/app/controllers/e9_crm/campaign_groups_controller.rb +8 -4
- data/app/controllers/e9_crm/campaign_subclass_controller.rb +15 -0
- data/app/controllers/e9_crm/campaigns_controller.rb +15 -23
- data/app/controllers/e9_crm/companies_controller.rb +11 -0
- data/app/controllers/e9_crm/email_campaigns_controller.rb +2 -0
- data/app/controllers/e9_crm/menu_options_controller.rb +2 -0
- data/app/controllers/e9_crm/resources_controller.rb +11 -1
- data/app/controllers/e9_crm/sales_campaigns_controller.rb +2 -0
- data/app/helpers/e9_crm/base_helper.rb +29 -0
- data/app/helpers/e9_crm/campaign_groups_helper.rb +1 -1
- data/app/helpers/e9_crm/campaigns_helper.rb +3 -4
- data/app/models/affiliate_campaign.rb +3 -1
- data/app/models/campaign.rb +7 -2
- data/app/models/campaign_group.rb +3 -1
- data/app/models/company.rb +5 -0
- data/app/models/contact.rb +19 -1
- data/app/models/menu_option.rb +4 -3
- data/app/models/sales_campaign.rb +3 -1
- data/app/views/e9_crm/affiliate_campaigns/_form_inner.html.haml +3 -3
- data/app/views/e9_crm/campaign_groups/_form_inner.html.haml +3 -0
- data/app/views/e9_crm/campaigns/_form_inner.html.haml +5 -8
- data/app/views/e9_crm/campaigns/_table.html.haml +2 -2
- data/app/views/e9_crm/companies/_header.html.haml +4 -0
- data/app/views/e9_crm/contacts/_header.html.haml +0 -21
- data/app/views/e9_crm/contacts/_index_sidebar.html.haml +1 -1
- data/app/views/e9_crm/contacts/show.html.haml +3 -1
- data/app/views/e9_crm/menu_options/_footer.html.haml +0 -0
- data/app/views/e9_crm/menu_options/_form_inner.html.haml +1 -1
- data/app/views/e9_crm/resources/_table.html.haml +5 -2
- data/app/views/e9_crm/sales_campaigns/_form_inner.html.haml +2 -2
- data/config/locales/e9.en.yml +0 -1
- data/config/locales/en.yml +11 -1
- data/e9_crm.gemspec +1 -0
- data/lib/e9_crm/e9_extensions.rb +20 -0
- data/lib/e9_crm/email.rb +16 -0
- data/lib/e9_crm/rails_extensions.rb +32 -1
- data/lib/e9_crm/version.rb +1 -1
- data/lib/e9_crm.rb +5 -0
- metadata +20 -5
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
+
*NOTE his plugin requires the private e9_base CMS gem and WILL NOT WORK without it.*
|
2
|
+
|
1
3
|
CRM Plugin for the e9 CMS
|
2
4
|
=========================
|
3
5
|
|
4
|
-
It should be noted that while this plugin is intended for use in the
|
5
|
-
e9 CMS, it does neither includes nor requires it.
|
6
|
-
|
7
6
|
To use, add as a gem and install by running:
|
8
7
|
|
9
8
|
rails g e9_crm:install
|
@@ -1,11 +1,15 @@
|
|
1
1
|
class E9Crm::CampaignGroupsController < E9Crm::ResourcesController
|
2
2
|
defaults :resource_class => CampaignGroup
|
3
3
|
include E9Rails::Controllers::Orderable
|
4
|
+
self.should_paginate_index = false
|
4
5
|
|
5
6
|
protected
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
|
8
|
+
def default_ordered_on
|
9
|
+
'name'
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_ordered_dir
|
13
|
+
'ASC'
|
10
14
|
end
|
11
15
|
end
|
@@ -1,6 +1,21 @@
|
|
1
1
|
class E9Crm::CampaignSubclassController < E9Crm::ResourcesController
|
2
2
|
|
3
|
+
def update
|
4
|
+
update! { parent_redirect_path }
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
create! { parent_redirect_path }
|
9
|
+
end
|
10
|
+
|
3
11
|
protected
|
12
|
+
def parent_redirect_path
|
13
|
+
campaigns_path(:type => type_param)
|
14
|
+
end
|
15
|
+
|
16
|
+
def type_param
|
17
|
+
resource_class.name[/(.*)Campaign/, 1].underscore
|
18
|
+
end
|
4
19
|
|
5
20
|
def add_index_breadcrumb
|
6
21
|
add_breadcrumb! Campaign.model_name.collection.titleize, campaigns_path
|
@@ -2,11 +2,11 @@ class E9Crm::CampaignsController < E9Crm::ResourcesController
|
|
2
2
|
defaults :resource_class => Campaign
|
3
3
|
include E9Rails::Controllers::Orderable
|
4
4
|
|
5
|
-
|
5
|
+
self.should_paginate_index = false
|
6
6
|
|
7
7
|
has_scope :of_group, :as => :group, :only => :index
|
8
8
|
|
9
|
-
has_scope :active, :only => :index do |_, scope, value|
|
9
|
+
has_scope :active, :only => :index, :default => 'true' do |_, scope, value|
|
10
10
|
scope.active(E9.true_value?(value))
|
11
11
|
end
|
12
12
|
|
@@ -14,31 +14,23 @@ class E9Crm::CampaignsController < E9Crm::ResourcesController
|
|
14
14
|
scope.of_type("#{value}_campaign".classify)
|
15
15
|
end
|
16
16
|
|
17
|
-
def reports
|
18
|
-
index!
|
19
|
-
end
|
20
|
-
|
21
17
|
protected
|
22
18
|
|
23
|
-
def
|
24
|
-
|
19
|
+
def collection_scope
|
20
|
+
end_of_association_chain.typed.includes(:campaign_group)
|
21
|
+
|
22
|
+
# NOTE this is a pretty ugly join just to be able to sort on campaign group name
|
23
|
+
end_of_association_chain.typed
|
24
|
+
.joins("left outer join campaign_groups on campaign_groups.id = campaigns.campaign_group_id")
|
25
|
+
.select("campaigns.*, campaign_groups.name campaign_group_name")
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
-
|
29
|
-
if params[:action] == 'reports'
|
30
|
-
scope = scope.select(
|
31
|
-
'campaigns.*, count(deals.id) won_deals_count, count(deals_campaigns.id) deals_count'
|
32
|
-
).joins([:deals, :won_deals])
|
33
|
-
else
|
34
|
-
# don't include NoCampaign normally
|
35
|
-
scope = scope.typed
|
36
|
-
end
|
37
|
-
scope
|
28
|
+
def default_ordered_on
|
29
|
+
'campaign_group_name,name'
|
38
30
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
get_collection_ivar || set_collection_ivar(collection_scope.all)
|
31
|
+
|
32
|
+
def default_ordered_dir
|
33
|
+
'ASC'
|
43
34
|
end
|
35
|
+
|
44
36
|
end
|
@@ -1,4 +1,15 @@
|
|
1
1
|
class E9Crm::CompaniesController < E9Crm::ResourcesController
|
2
2
|
defaults :resource_class => Company
|
3
3
|
include E9Rails::Controllers::Orderable
|
4
|
+
include E9::DestroyRestricted::Controller
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def default_ordered_on
|
9
|
+
'name'
|
10
|
+
end
|
11
|
+
|
12
|
+
def default_ordered_dir
|
13
|
+
'ASC'
|
14
|
+
end
|
4
15
|
end
|
@@ -2,6 +2,8 @@ class E9Crm::MenuOptionsController < E9Crm::ResourcesController
|
|
2
2
|
defaults :resource_class => MenuOption
|
3
3
|
include E9Rails::Controllers::Sortable
|
4
4
|
|
5
|
+
self.should_paginate_index = false
|
6
|
+
|
5
7
|
has_scope :options_for, :as => :key, :only => :index
|
6
8
|
|
7
9
|
# NOTE The reason this is set in a filter instead of just a default scope value
|
@@ -1,6 +1,12 @@
|
|
1
1
|
class E9Crm::ResourcesController < E9Crm::BaseController
|
2
2
|
include E9Rails::Helpers::ResourceErrorMessages
|
3
|
-
|
3
|
+
|
4
|
+
# NOTE depending on e9_base pagination (which should eventually use this module)
|
5
|
+
#include E9Rails::Helpers::Pagination
|
6
|
+
|
7
|
+
# TODO implement role on e9_crm models?
|
8
|
+
#include E9::Roles::Controller
|
9
|
+
#filter_access_to :update, :edit, :attribute_check => true, :load_method => :filter_target, :context => :admin
|
4
10
|
|
5
11
|
class_inheritable_accessor :should_paginate_index
|
6
12
|
self.should_paginate_index = true
|
@@ -25,6 +31,10 @@ class E9Crm::ResourcesController < E9Crm::BaseController
|
|
25
31
|
|
26
32
|
protected
|
27
33
|
|
34
|
+
def filter_target
|
35
|
+
resource
|
36
|
+
end
|
37
|
+
|
28
38
|
# NOTE parent is defined so it's always available, it will be overridden on controllers which have belongs_to routes
|
29
39
|
def parent; end
|
30
40
|
helper_method :parent
|
@@ -1,5 +1,34 @@
|
|
1
1
|
module E9Crm::BaseHelper
|
2
2
|
|
3
|
+
def kramdown(string)
|
4
|
+
Kramdown::Document.new(string).to_html.html_safe
|
5
|
+
end
|
6
|
+
|
7
|
+
alias :k :kramdown
|
8
|
+
|
9
|
+
def help_tooltip(string)
|
10
|
+
return <<-HTML.strip.html_safe
|
11
|
+
<span class="help" rel="tooltip" title="#{CGI.escape_html(string)}">#{t(:inline_help_link)}</span>
|
12
|
+
HTML
|
13
|
+
end
|
14
|
+
|
15
|
+
def help_label(form_or_id, key, options = {})
|
16
|
+
options[:key] ||= :"#{key}_help"
|
17
|
+
|
18
|
+
help_title = options.delete(:title) || resource_humanize(options.delete(:key))
|
19
|
+
|
20
|
+
str = ''.html_safe
|
21
|
+
str.safe_concat resource_humanize(key)
|
22
|
+
str.safe_concat ' '
|
23
|
+
str.safe_concat help_tooltip(help_title)
|
24
|
+
|
25
|
+
if form_or_id.respond_to?(:label)
|
26
|
+
form_or_id.label(key, str, options)
|
27
|
+
else
|
28
|
+
label_tag(form_or_id, str, options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
3
32
|
##
|
4
33
|
# Field maps
|
5
34
|
#
|
@@ -4,7 +4,7 @@ module E9Crm::CampaignsHelper
|
|
4
4
|
end
|
5
5
|
|
6
6
|
def display_campaign_code(val)
|
7
|
-
val || 'n/a'
|
7
|
+
val && "?#{E9Crm.query_param}=#{val}" || 'n/a'
|
8
8
|
end
|
9
9
|
|
10
10
|
def display_campaign_type(val)
|
@@ -18,7 +18,7 @@ module E9Crm::CampaignsHelper
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def campaign_group_select_options
|
21
|
-
options = CampaignGroup.select('name, id').all.map {|c| [c.name, c.id] }
|
21
|
+
options = CampaignGroup.select('name, id').ordered.all.map {|c| [c.name, c.id] }
|
22
22
|
options.unshift(['All Groups', nil])
|
23
23
|
options_for_select(options)
|
24
24
|
end
|
@@ -29,8 +29,7 @@ module E9Crm::CampaignsHelper
|
|
29
29
|
|
30
30
|
def campaign_active_select_options
|
31
31
|
options = [
|
32
|
-
['
|
33
|
-
['Active', true],
|
32
|
+
['Active', true],
|
34
33
|
['Inactive', false]
|
35
34
|
]
|
36
35
|
options_for_select(options)
|
data/app/models/campaign.rb
CHANGED
@@ -26,9 +26,14 @@ class Campaign < ActiveRecord::Base
|
|
26
26
|
NoCampaign.first || NoCampaign.create
|
27
27
|
end
|
28
28
|
|
29
|
+
validates :name, :presence => true,
|
30
|
+
:uniqueness => { :allow_blank => true, :case_sensitive => false }
|
31
|
+
|
29
32
|
validates :code, :presence => { :unless => lambda {|r| r.is_a?(NoCampaign) } },
|
30
|
-
:length => { :maximum => 32 },
|
31
|
-
:
|
33
|
+
:length => { :maximum => 32 },
|
34
|
+
:format => { :allow_blank => true, :with => /^[\w\d]+$/ },
|
35
|
+
:uniqueness => { :case_sensitive => false, :allow_blank => true }
|
36
|
+
|
32
37
|
validates :affiliate_fee, :numericality => true
|
33
38
|
validates :sales_fee, :numericality => true
|
34
39
|
|
@@ -3,7 +3,9 @@
|
|
3
3
|
class CampaignGroup < ActiveRecord::Base
|
4
4
|
has_many :campaigns
|
5
5
|
|
6
|
-
validates :name, :uniqueness => { :
|
6
|
+
validates :name, :presence => true, :uniqueness => { :allow_nil => true, :case_sensitive => false }
|
7
|
+
|
8
|
+
scope :ordered, lambda { order(arel_table[:name].asc) }
|
7
9
|
|
8
10
|
def to_s
|
9
11
|
name
|
data/app/models/company.rb
CHANGED
data/app/models/contact.rb
CHANGED
@@ -8,12 +8,13 @@ class Contact < ActiveRecord::Base
|
|
8
8
|
include Rails.application.routes.url_helpers
|
9
9
|
|
10
10
|
before_validation :ensure_user_references
|
11
|
+
before_destroy :ensure_no_associated_deals
|
11
12
|
|
12
13
|
##
|
13
14
|
# Associations
|
14
15
|
#
|
15
16
|
belongs_to :company
|
16
|
-
has_many :owned_deals, :class_name => 'Deal'
|
17
|
+
has_many :owned_deals, :class_name => 'Deal', :dependent => :restrict
|
17
18
|
has_and_belongs_to_many :associated_deals, :class_name => 'Deal'
|
18
19
|
|
19
20
|
has_many :users, :inverse_of => :contact, :dependent => :nullify do
|
@@ -83,6 +84,8 @@ class Contact < ActiveRecord::Base
|
|
83
84
|
end
|
84
85
|
accepts_nested_attributes_for :users, :allow_destroy => true
|
85
86
|
|
87
|
+
delegate :email, :to => 'users.primary.first', :allow_nil => true
|
88
|
+
|
86
89
|
def page_views
|
87
90
|
PageView.by_user(users)
|
88
91
|
end
|
@@ -149,6 +152,7 @@ class Contact < ActiveRecord::Base
|
|
149
152
|
scope :sales_persons, lambda { where(:status => Status::SalesPerson) }
|
150
153
|
scope :affiliates, lambda { where(:status => Status::Affiliate) }
|
151
154
|
scope :contacts, lambda { where(:status => Status::Contact) }
|
155
|
+
scope :ordered, lambda { order(arel_table[:first_name].asc) }
|
152
156
|
|
153
157
|
scope :by_title, lambda {|val| where(:title => val) }
|
154
158
|
scope :by_company, lambda {|val| where(:company_id => val) }
|
@@ -284,6 +288,10 @@ class Contact < ActiveRecord::Base
|
|
284
288
|
end
|
285
289
|
end
|
286
290
|
|
291
|
+
def to_liquid
|
292
|
+
Drop.new(self)
|
293
|
+
end
|
294
|
+
|
287
295
|
protected
|
288
296
|
|
289
297
|
def _assign_initialization_defaults
|
@@ -307,6 +315,16 @@ class Contact < ActiveRecord::Base
|
|
307
315
|
attributes.keys.member?('email') && attributes['email'].blank?
|
308
316
|
end
|
309
317
|
|
318
|
+
def ensure_no_associated_deals
|
319
|
+
unless self.associated_deals.empty?
|
320
|
+
object.errors.add(:associated_deals, :delete_restricted)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
class Drop < ::E9::Liquid::Drops::Base
|
325
|
+
source_methods :first_name, :last_name, :name, :email, :title, :company_name
|
326
|
+
end
|
327
|
+
|
310
328
|
module Status
|
311
329
|
VALUES = %w(contact sales_person affiliate)
|
312
330
|
Contact = VALUES[0]
|
data/app/models/menu_option.rb
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
#
|
3
3
|
class MenuOption < ActiveRecord::Base
|
4
4
|
KEYS = [
|
5
|
+
#'Task Category',
|
6
|
+
#'Task Status',
|
7
|
+
'Address',
|
5
8
|
'Deal Category',
|
6
9
|
'Email',
|
7
10
|
'Instant Messaging Handle',
|
8
11
|
'Phone Number',
|
9
|
-
#'Task Category',
|
10
|
-
#'Task Status',
|
11
12
|
'Website'
|
12
13
|
].freeze
|
13
14
|
|
@@ -16,7 +17,7 @@ class MenuOption < ActiveRecord::Base
|
|
16
17
|
|
17
18
|
acts_as_list :scope => 'menu_options.key = \"#{key}\"'
|
18
19
|
|
19
|
-
scope :options_for, lambda {|key| where(:key => key) }
|
20
|
+
scope :options_for, lambda {|key| where(:key => key).order('menu_options.position ASC') }
|
20
21
|
|
21
22
|
##
|
22
23
|
# A direct SQL selection of values for a given key
|
@@ -3,8 +3,8 @@
|
|
3
3
|
%fieldset
|
4
4
|
%legend= e9_t(:affiliate_information_legend, :scope => 'e9_crm.campaigns')
|
5
5
|
.field
|
6
|
-
= f.label :
|
7
|
-
= f.collection_select :affiliate_id, Contact.affiliates.all, :id, :name, :prompt => true
|
6
|
+
= f.label :affilate, nil, :class => :req, :for => 'campaign_affiliate_id'
|
7
|
+
= f.collection_select :affiliate_id, Contact.affiliates.ordered.all, :id, :name, {:prompt => true}, :id => 'campaign_affiliate_id'
|
8
8
|
.field
|
9
|
-
= f
|
9
|
+
= help_label f, :affiliate_fee
|
10
10
|
= f.text_field :affiliate_fee
|
@@ -2,20 +2,17 @@
|
|
2
2
|
%legend= e9_t(:campaign_information_legend, :scope => 'e9_crm.campaigns')
|
3
3
|
.field
|
4
4
|
= f.label :campaign_group_id
|
5
|
-
= f.collection_select :campaign_group_id, CampaignGroup.all, :id, :name, :include_blank => 'No Group'
|
5
|
+
= f.collection_select :campaign_group_id, CampaignGroup.ordered.all, :id, :name, :include_blank => 'No Group'
|
6
6
|
.field
|
7
|
-
= f.label :name
|
7
|
+
= f.label :name, nil, :class => :req
|
8
8
|
= f.text_field :name
|
9
9
|
- if f.object.new_record?
|
10
10
|
.field#campaign_code_field
|
11
|
-
= f.label :code
|
11
|
+
= f.label :code, nil, :class => :req
|
12
12
|
= f.text_field :code
|
13
13
|
.field
|
14
|
-
|
15
|
-
|
16
|
-
%span.help{:title => e9_t(:code_help, :scope => 'e9_crm.campaigns', :code => E9Crm.query_param)}= t(:inline_help_link)
|
17
|
-
#campaign_code_hint= "?#{E9Crm.query_param}=#{f.object.code}"
|
14
|
+
= help_label :campaign_code_hint, :code_hint, :title => t('activerecord.attributes.campaign.code_hint_help', :code => E9Crm.query_param)
|
15
|
+
#campaign_code_hint= display_campaign_code(f.object.code || '')
|
18
16
|
.field
|
19
17
|
= f.label :active
|
20
18
|
= f.check_box :active
|
21
|
-
|
@@ -3,7 +3,7 @@
|
|
3
3
|
%tr
|
4
4
|
%th= orderable_column_link(:type)
|
5
5
|
%th= orderable_column_link(:name)
|
6
|
-
%th= orderable_column_link('
|
6
|
+
%th= orderable_column_link('campaign_group_name', :campaign_group)
|
7
7
|
%th= orderable_column_link(:code)
|
8
8
|
%th= orderable_column_link(:affiliate_fee)
|
9
9
|
%th= orderable_column_link(:sales_fee)
|
@@ -20,7 +20,7 @@
|
|
20
20
|
%td.record-name
|
21
21
|
= record.name
|
22
22
|
%td.record-campaign-group
|
23
|
-
= record.
|
23
|
+
= record.campaign_group_name || e9_t(:no_group, :scope => 'e9_crm.campaigns')
|
24
24
|
%td.record-code
|
25
25
|
= display_campaign_code(record.code)
|
26
26
|
%td.record-affiliate-fee
|
@@ -1,21 +0,0 @@
|
|
1
|
-
.toolbar
|
2
|
-
.toolbar-left
|
3
|
-
= form_tag(resource_class, :method => :get, :id => 'contact_search_form') do
|
4
|
-
= label_tag 'contact_search_field', t(:search)
|
5
|
-
= text_field_tag 'search', params[:search], :id => 'contact_search_field'
|
6
|
-
= submit_tag t(:go), :name => nil
|
7
|
-
= submit_tag t(:clear), :name => nil, :id => 'contact_search_clear'
|
8
|
-
.toolbar-middle
|
9
|
-
- if (tag = contact_email_template_select_tag).present?
|
10
|
-
= form_tag new_contact_email_path, :method => :get, :id => 'contact_email_form', 'data-empty' => e9_t(:no_contacts_notification), 'data-count' => @contact_ids.length do
|
11
|
-
= tag
|
12
|
-
= hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_email_uids'
|
13
|
-
= submit_tag e9_t(:send_email_template), :name => nil
|
14
|
-
- if (tag = contact_newsletter_select_tag).present?
|
15
|
-
= form_tag send_email_admin_user_email_path('__ID__'), :method => :put, :id => 'contact_newsletter_form', 'data-confirm' => e9_t(:contact_newsletter_confirmation, :count => collection.length), 'data-empty' => e9_t(:no_contacts_notification), 'data-count' => @contact_ids.length do
|
16
|
-
= tag
|
17
|
-
= hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_newsletter_uids'
|
18
|
-
= submit_tag e9_t(:send_email_newsletter), :name => nil
|
19
|
-
.toolbar-right
|
20
|
-
= link_to_new_resource(Contact)
|
21
|
-
= link_to_new_resource(Company)
|
@@ -15,10 +15,12 @@
|
|
15
15
|
- if company = resource.company
|
16
16
|
.contact-company
|
17
17
|
%label= company.name
|
18
|
+
|
18
19
|
.contact-company-links.actions
|
19
20
|
= google_search_link(company.name)
|
20
21
|
= google_news_link(company.name)
|
22
|
+
|
21
23
|
- if company.info.present?
|
22
|
-
=
|
24
|
+
= k(company.info)
|
23
25
|
.contact-sidebar
|
24
26
|
= render 'sidebar'
|
File without changes
|
@@ -3,8 +3,11 @@
|
|
3
3
|
%table.records{:class => sortable_controller? ? 'sortable' : nil }
|
4
4
|
%thead
|
5
5
|
%tr
|
6
|
-
- field_map[:fields].keys.each do |
|
7
|
-
|
6
|
+
- field_map[:fields].keys.each do |key|
|
7
|
+
- if key.is_a?(Symbol)
|
8
|
+
%th= resource_class.human_attribute_name(key)
|
9
|
+
- else
|
10
|
+
%th= orderable_column_link(key)
|
8
11
|
%th= e9_t(:actions)
|
9
12
|
%tbody
|
10
13
|
- if collection.empty?
|
@@ -4,8 +4,8 @@
|
|
4
4
|
%legend= e9_t(:salesperson_information_legend, :scope => 'e9_crm.campaigns')
|
5
5
|
.field
|
6
6
|
= f.label :sales_person_id
|
7
|
-
= f.collection_select :sales_person_id, Contact.sales_persons.all, :id, :name, :prompt => true
|
7
|
+
= f.collection_select :sales_person_id, Contact.sales_persons.ordered.all, :id, :name, :prompt => true
|
8
8
|
.field
|
9
|
-
= f
|
9
|
+
= help_label f, :sales_fee
|
10
10
|
= f.text_field :sales_fee
|
11
11
|
|
data/config/locales/e9.en.yml
CHANGED
@@ -38,4 +38,3 @@ en:
|
|
38
38
|
campaign_information_legend: Campaign Information
|
39
39
|
salesperson_information_legend: Salesperson Information
|
40
40
|
affiliate_information_legend: Affiliate Information
|
41
|
-
code_help: "Be careful when creating tracking codes. They are NOT EDITABLE after you save them. To track the success of this campaign, you can append ?%{code}={Your Code} to the end of any and all URLs on your website. It might look something like this: http://www.example.com/about-us?%{code}=alpha, where \"alpha\" represents the code you created. You can provide this tracking URL to a salesperson or an affiliate or it can be placed at the end of a link in any of your advertisements."
|
data/config/locales/en.yml
CHANGED
@@ -36,6 +36,11 @@ en:
|
|
36
36
|
merge_required: 'Merge Required! <a href="%{merge_path}">MERGE ME</a>.'
|
37
37
|
|
38
38
|
models:
|
39
|
+
campaign:
|
40
|
+
not_a_number: "%{attribute} must be a number (maximum 2 decimal places)."
|
41
|
+
attributes:
|
42
|
+
code:
|
43
|
+
invalid: "%{attribute} must be comprised of letters and numbers only."
|
39
44
|
contact:
|
40
45
|
attributes:
|
41
46
|
users:
|
@@ -44,7 +49,7 @@ en:
|
|
44
49
|
contact_email:
|
45
50
|
attributes:
|
46
51
|
contact_ids:
|
47
|
-
blank: "You cannot send an
|
52
|
+
blank: "You cannot send an email with no recipients!"
|
48
53
|
user_ids:
|
49
54
|
blank: "None of the contacts selected are configured with primary emails. Please correct this and try again."
|
50
55
|
deal:
|
@@ -86,6 +91,11 @@ en:
|
|
86
91
|
campaign:
|
87
92
|
name: Name
|
88
93
|
code_hint: Append to URL
|
94
|
+
code_hint_help: "Be careful when creating tracking codes. They are NOT EDITABLE after you save them.\n\nTo track the success of this campaign, you can append ?%{code}={Your Code} to the end of any and all URLs on your website.\n\nIt might look something like this: http://www.example.com/about-us?%{code}=alpha, where \"alpha\" represents the code you created.\n\nYou can provide this tracking URL to a salesperson or an affiliate or it can be placed at the end of a link in any of your advertisements."
|
95
|
+
affiliate_fee: Affiliate Fee
|
96
|
+
affiliate_fee_help: This is the fee payable for each lead this affiliate sends you where it converts to a sale.
|
97
|
+
sales_fee: Sales Fee
|
98
|
+
sales_fee_help: This is the fee payable for each lead this salesperson sends you where it converts to a sale.
|
89
99
|
contact:
|
90
100
|
avatar: Photo
|
91
101
|
users: Email Addresses
|
data/e9_crm.gemspec
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
module E9Crm
|
2
|
+
#
|
3
|
+
# Extends E9Base's Email to attempt to embed the Contact
|
4
|
+
# for the recipient in the liquid template arguments.
|
5
|
+
#
|
6
|
+
module Email
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
def locals_with_contact
|
11
|
+
default_locals.merge({
|
12
|
+
:contact => recipient.try(:contact)
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :default_locals :this_locals
|
17
|
+
alias :this_locals :locals_with_contact
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/e9_crm/email.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module E9Crm
|
2
|
+
module Email
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def locals_with_contact
|
7
|
+
default_locals.merge({
|
8
|
+
:contact => recipient.try(:contact)
|
9
|
+
})
|
10
|
+
end
|
11
|
+
|
12
|
+
alias :default_locals :this_locals
|
13
|
+
alias :this_locals :locals_with_contact
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -16,6 +16,37 @@ class Array
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
|
20
|
+
#
|
21
|
+
# Money is too clever by half and attempts to deal with parsing Strings into
|
22
|
+
# currency e.g.
|
23
|
+
#
|
24
|
+
# "asdf 0.23 asdf".to_money #=> #<Money cents:23 currency:USD>
|
25
|
+
#
|
26
|
+
# This is problematic if you want to actually validate money as it parses most
|
27
|
+
# bogus strings to zero, so unless you want to validate > 0, most any input
|
28
|
+
# will pass validation.
|
29
|
+
#
|
30
|
+
# This silly hack prevents "asdf".to_money from parsing to 0 cents, instead
|
31
|
+
# returning itself. The #cents method allows for our composed_of column to
|
32
|
+
# still work, simply returning self, which would fail a numericality validation.
|
33
|
+
#
|
34
|
+
require 'money'
|
35
|
+
|
36
|
+
class String
|
37
|
+
def to_money(currency = nil)
|
38
|
+
if match /^$|[^\$\d\.\,]/
|
39
|
+
self
|
40
|
+
else
|
41
|
+
Money.parse(self, currency)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def cents
|
46
|
+
self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
19
50
|
class ActiveRecord::Base
|
20
51
|
#
|
21
52
|
# Basic conversion for "money" columns using the Money class and Rails composed_of
|
@@ -26,7 +57,7 @@ class ActiveRecord::Base
|
|
26
57
|
composed_of :#{column_name},
|
27
58
|
:class_name => 'Money',
|
28
59
|
:mapping => %w(#{column_name} cents),
|
29
|
-
:converter => Proc.new {
|
60
|
+
:converter => Proc.new {|v| v.respond_to?(:to_money) ? v.to_money : v }
|
30
61
|
EVAL
|
31
62
|
end
|
32
63
|
end
|
data/lib/e9_crm/version.rb
CHANGED
data/lib/e9_crm.rb
CHANGED
@@ -5,6 +5,8 @@ require 'money'
|
|
5
5
|
require 'inherited_resources'
|
6
6
|
require 'will_paginate'
|
7
7
|
require 'has_scope'
|
8
|
+
require 'kramdown'
|
9
|
+
require 'e9_base'
|
8
10
|
|
9
11
|
require 'e9_crm/rails_extensions'
|
10
12
|
|
@@ -12,6 +14,7 @@ module E9Crm
|
|
12
14
|
autoload :VERSION, 'e9_crm/version'
|
13
15
|
autoload :Controller, 'e9_crm/controller'
|
14
16
|
autoload :Model, 'e9_crm/model'
|
17
|
+
autoload :Email, 'e9_crm/email'
|
15
18
|
autoload :TrackingController, 'e9_crm/tracking_controller'
|
16
19
|
|
17
20
|
mattr_accessor :cookie_name
|
@@ -52,6 +55,8 @@ module E9Crm
|
|
52
55
|
|
53
56
|
ActionController::Base.send(:include, E9Crm::Controller)
|
54
57
|
|
58
|
+
::Email.send(:include, E9Crm::Email)
|
59
|
+
|
55
60
|
E9Crm.tracking_controllers.each do |controller|
|
56
61
|
controller.send(:include, E9Crm::TrackingController)
|
57
62
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: e9_crm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.10
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Travis Cox
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-05-
|
13
|
+
date: 2011-05-26 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -90,13 +90,23 @@ dependencies:
|
|
90
90
|
version: "0"
|
91
91
|
type: :runtime
|
92
92
|
version_requirements: *id007
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: kramdown
|
95
|
+
prerelease: false
|
96
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0.13"
|
102
|
+
type: :runtime
|
103
|
+
version_requirements: *id008
|
93
104
|
description: |
|
105
|
+
*NOTE his plugin requires the private e9_base CMS gem and WILL NOT WORK without it.*
|
106
|
+
|
94
107
|
CRM Plugin for the e9 CMS
|
95
108
|
=========================
|
96
109
|
|
97
|
-
It should be noted that while this plugin is intended for use in the
|
98
|
-
e9 CMS, it does neither includes nor requires it.
|
99
|
-
|
100
110
|
To use, add as a gem and install by running:
|
101
111
|
|
102
112
|
rails g e9_crm:install
|
@@ -207,6 +217,7 @@ files:
|
|
207
217
|
- app/views/e9_crm/advertising_campaigns/costs.html.haml
|
208
218
|
- app/views/e9_crm/affiliate_campaigns/_form_inner.html.haml
|
209
219
|
- app/views/e9_crm/campaign_groups/_footer.html.haml
|
220
|
+
- app/views/e9_crm/campaign_groups/_form_inner.html.haml
|
210
221
|
- app/views/e9_crm/campaign_groups/_header.html.haml
|
211
222
|
- app/views/e9_crm/campaigns/_footer.html.haml
|
212
223
|
- app/views/e9_crm/campaigns/_form_inner.html.haml
|
@@ -215,6 +226,7 @@ files:
|
|
215
226
|
- app/views/e9_crm/campaigns/_table.html.haml
|
216
227
|
- app/views/e9_crm/campaigns/reports.html.haml
|
217
228
|
- app/views/e9_crm/companies/_form_inner.html.haml
|
229
|
+
- app/views/e9_crm/companies/_header.html.haml
|
218
230
|
- app/views/e9_crm/contact_emails/_form.html.haml
|
219
231
|
- app/views/e9_crm/contact_emails/_form_inner.html.haml
|
220
232
|
- app/views/e9_crm/contact_emails/destroy.js.erb
|
@@ -268,6 +280,7 @@ files:
|
|
268
280
|
- app/views/e9_crm/leads/_form.html.haml
|
269
281
|
- app/views/e9_crm/leads/create.js.erb
|
270
282
|
- app/views/e9_crm/leads/new.html.haml
|
283
|
+
- app/views/e9_crm/menu_options/_footer.html.haml
|
271
284
|
- app/views/e9_crm/menu_options/_form_inner.html.haml
|
272
285
|
- app/views/e9_crm/menu_options/_header.html.haml
|
273
286
|
- app/views/e9_crm/new_content_subscription_offers/_form_inner.html.haml
|
@@ -310,6 +323,8 @@ files:
|
|
310
323
|
- e9_crm.gemspec
|
311
324
|
- lib/e9_crm.rb
|
312
325
|
- lib/e9_crm/controller.rb
|
326
|
+
- lib/e9_crm/e9_extensions.rb
|
327
|
+
- lib/e9_crm/email.rb
|
313
328
|
- lib/e9_crm/model.rb
|
314
329
|
- lib/e9_crm/rails_extensions.rb
|
315
330
|
- lib/e9_crm/tracking_controller.rb
|