e9_crm 0.1.8 → 0.1.10
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.
- 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
|