e9_crm 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +105 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/app/controllers/e9_crm/advertising_campaigns_controller.rb +3 -0
- data/app/controllers/e9_crm/affiliate_campaigns_controller.rb +3 -0
- data/app/controllers/e9_crm/base_controller.rb +5 -0
- data/app/controllers/e9_crm/campaign_groups_controller.rb +3 -0
- data/app/controllers/e9_crm/campaigns_controller.rb +4 -0
- data/app/controllers/e9_crm/companies_controller.rb +3 -0
- data/app/controllers/e9_crm/contact_emails_controller.rb +38 -0
- data/app/controllers/e9_crm/contact_merges_controller.rb +26 -0
- data/app/controllers/e9_crm/contacts_controller.rb +46 -0
- data/app/controllers/e9_crm/dated_costs_controller.rb +4 -0
- data/app/controllers/e9_crm/deals_controller.rb +19 -0
- data/app/controllers/e9_crm/email_campaigns_controller.rb +3 -0
- data/app/controllers/e9_crm/email_templates.controller.rb +3 -0
- data/app/controllers/e9_crm/menu_options_controller.rb +26 -0
- data/app/controllers/e9_crm/offers_controller.rb +3 -0
- data/app/controllers/e9_crm/page_views_controller.rb +20 -0
- data/app/controllers/e9_crm/record_attributes_controller.rb +3 -0
- data/app/controllers/e9_crm/reports_controller.rb +2 -0
- data/app/controllers/e9_crm/resources_controller.rb +43 -0
- data/app/controllers/e9_crm/sales_campaigns_controller.rb +3 -0
- data/app/helpers/e9_crm/base_helper.rb +77 -0
- data/app/helpers/e9_crm/campaigns_helper.rb +14 -0
- data/app/helpers/e9_crm/contact_merges_helper.rb +17 -0
- data/app/helpers/e9_crm/contacts_helper.rb +27 -0
- data/app/helpers/e9_crm/deals_helper.rb +15 -0
- data/app/helpers/e9_crm/menu_options_helper.rb +11 -0
- data/app/helpers/e9_crm/page_views_helper.rb +2 -0
- data/app/models/address_attribute.rb +4 -0
- data/app/models/advertising_campaign.rb +15 -0
- data/app/models/affiliate.rb +4 -0
- data/app/models/affiliate_campaign.rb +15 -0
- data/app/models/campaign.rb +34 -0
- data/app/models/campaign_group.rb +5 -0
- data/app/models/company.rb +4 -0
- data/app/models/contact.rb +258 -0
- data/app/models/contact_email.rb +49 -0
- data/app/models/dated_cost.rb +9 -0
- data/app/models/deal.rb +83 -0
- data/app/models/email_campaign.rb +13 -0
- data/app/models/email_template.rb +7 -0
- data/app/models/instant_messaging_handle_attribute.rb +4 -0
- data/app/models/menu_option.rb +33 -0
- data/app/models/offer.rb +50 -0
- data/app/models/page_view.rb +80 -0
- data/app/models/phone_number_attribute.rb +4 -0
- data/app/models/record_attribute.rb +41 -0
- data/app/models/sales_campaign.rb +15 -0
- data/app/models/sales_person.rb +4 -0
- data/app/models/tracking_cookie.rb +61 -0
- data/app/models/website_attribute.rb +4 -0
- data/app/observers/deal_observer.rb +11 -0
- data/app/uploaders/file_uploader.rb +34 -0
- data/app/views/e9_crm/campaigns/_form_inner.html.haml +5 -0
- data/app/views/e9_crm/contact_emails/_form.html.haml +7 -0
- data/app/views/e9_crm/contact_emails/_form_inner.html.haml +11 -0
- data/app/views/e9_crm/contact_emails/destroy.js.erb +3 -0
- data/app/views/e9_crm/contact_emails/send_email.js.erb +1 -0
- data/app/views/e9_crm/contact_merges/_field.html.haml +10 -0
- data/app/views/e9_crm/contact_merges/_form.html.haml +10 -0
- data/app/views/e9_crm/contact_merges/new.html.haml +2 -0
- data/app/views/e9_crm/contacts/_details.html.haml +22 -0
- data/app/views/e9_crm/contacts/_form_inner.html.haml +51 -0
- data/app/views/e9_crm/contacts/_header.html.haml +19 -0
- data/app/views/e9_crm/contacts/_tag_table.html.haml +15 -0
- data/app/views/e9_crm/contacts/index.html.haml +13 -0
- data/app/views/e9_crm/contacts/index.js.erb +5 -0
- data/app/views/e9_crm/contacts/merge.html.haml +1 -0
- data/app/views/e9_crm/contacts/templates.js.erb +1 -0
- data/app/views/e9_crm/deals/_form_inner.html.haml +5 -0
- data/app/views/e9_crm/deals/_header.html.haml +0 -0
- data/app/views/e9_crm/deals/leads.html.haml +13 -0
- data/app/views/e9_crm/email_templates/_form_inner.html.haml +9 -0
- data/app/views/e9_crm/menu_options/_form_inner.html.haml +6 -0
- data/app/views/e9_crm/menu_options/_header.html.haml +8 -0
- data/app/views/e9_crm/offers/_form.html.haml +7 -0
- data/app/views/e9_crm/offers/_form_inner.html.haml +42 -0
- data/app/views/e9_crm/offers/_form_inner.html.haml.bak +43 -0
- data/app/views/e9_crm/page_views/_table.html.haml +25 -0
- data/app/views/e9_crm/record_attributes/_address_attribute.html.haml +5 -0
- data/app/views/e9_crm/record_attributes/_instant_messaging_handle_attribute.html.haml +5 -0
- data/app/views/e9_crm/record_attributes/_phone_number_attribute.html.haml +5 -0
- data/app/views/e9_crm/record_attributes/_record_attribute.html.haml +10 -0
- data/app/views/e9_crm/record_attributes/_templates.js.erb +12 -0
- data/app/views/e9_crm/record_attributes/_user.html.haml +23 -0
- data/app/views/e9_crm/record_attributes/_website_attribute.html.haml +5 -0
- data/app/views/e9_crm/resources/_footer.html.haml +1 -0
- data/app/views/e9_crm/resources/_form.html.haml +7 -0
- data/app/views/e9_crm/resources/_form_inner.html.haml +5 -0
- data/app/views/e9_crm/resources/_header.html.haml +0 -0
- data/app/views/e9_crm/resources/_table.html.haml +21 -0
- data/app/views/e9_crm/resources/create.js.erb +6 -0
- data/app/views/e9_crm/resources/destroy.js.erb +3 -0
- data/app/views/e9_crm/resources/edit.html.haml +2 -0
- data/app/views/e9_crm/resources/index.html.haml +13 -0
- data/app/views/e9_crm/resources/index.js.erb +1 -0
- data/app/views/e9_crm/resources/new.html.haml +2 -0
- data/app/views/e9_crm/resources/show.html.haml +2 -0
- data/app/views/e9_crm/resources/update.js.erb +5 -0
- data/config/initializers/inflections.rb +3 -0
- data/config/locales/e9.en.yml +28 -0
- data/config/locales/en.yml +63 -0
- data/config/routes.rb +61 -0
- data/e9_crm.gemspec +29 -0
- data/lib/e9_crm/model.rb +63 -0
- data/lib/e9_crm/rails_extensions.rb +98 -0
- data/lib/e9_crm/tracking_controller.rb +78 -0
- data/lib/e9_crm/version.rb +3 -0
- data/lib/e9_crm.rb +59 -0
- data/lib/generators/e9_crm/install_generator.rb +32 -0
- data/lib/generators/e9_crm/templates/create_e9_crm_tables.rb +107 -0
- data/lib/generators/e9_crm/templates/initializer.rb +4 -0
- data/lib/generators/e9_crm/templates/javascript.js +187 -0
- data/test/functional/e9_crm/campaign_types_controller_test.rb +49 -0
- data/test/functional/home_controller_test.rb +8 -0
- metadata +283 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
e9_crm (0.1.0)
|
5
|
+
e9_rails (~> 0.0.4)
|
6
|
+
e9_tags (~> 0.0.2)
|
7
|
+
has_scope
|
8
|
+
inherited_resources (~> 1.1.2)
|
9
|
+
money
|
10
|
+
rails (~> 3.0.0)
|
11
|
+
will_paginate
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: http://rubygems.org/
|
15
|
+
specs:
|
16
|
+
abstract (1.0.0)
|
17
|
+
actionmailer (3.0.5)
|
18
|
+
actionpack (= 3.0.5)
|
19
|
+
mail (~> 2.2.15)
|
20
|
+
actionpack (3.0.5)
|
21
|
+
activemodel (= 3.0.5)
|
22
|
+
activesupport (= 3.0.5)
|
23
|
+
builder (~> 2.1.2)
|
24
|
+
erubis (~> 2.6.6)
|
25
|
+
i18n (~> 0.4)
|
26
|
+
rack (~> 1.2.1)
|
27
|
+
rack-mount (~> 0.6.13)
|
28
|
+
rack-test (~> 0.5.7)
|
29
|
+
tzinfo (~> 0.3.23)
|
30
|
+
activemodel (3.0.5)
|
31
|
+
activesupport (= 3.0.5)
|
32
|
+
builder (~> 2.1.2)
|
33
|
+
i18n (~> 0.4)
|
34
|
+
activerecord (3.0.5)
|
35
|
+
activemodel (= 3.0.5)
|
36
|
+
activesupport (= 3.0.5)
|
37
|
+
arel (~> 2.0.2)
|
38
|
+
tzinfo (~> 0.3.23)
|
39
|
+
activeresource (3.0.5)
|
40
|
+
activemodel (= 3.0.5)
|
41
|
+
activesupport (= 3.0.5)
|
42
|
+
activesupport (3.0.5)
|
43
|
+
acts-as-taggable-on (2.0.6)
|
44
|
+
arel (2.0.9)
|
45
|
+
builder (2.1.2)
|
46
|
+
e9_rails (0.0.4)
|
47
|
+
inherited_resources
|
48
|
+
rails (~> 3.0.0)
|
49
|
+
e9_tags (0.0.2)
|
50
|
+
acts-as-taggable-on (~> 2.0.6)
|
51
|
+
rails (~> 3.0.0)
|
52
|
+
erubis (2.6.6)
|
53
|
+
abstract (>= 1.0.0)
|
54
|
+
has_scope (0.5.0)
|
55
|
+
i18n (0.5.0)
|
56
|
+
inherited_resources (1.1.2)
|
57
|
+
has_scope (~> 0.5.0)
|
58
|
+
responders (~> 0.6.0)
|
59
|
+
mail (2.2.15)
|
60
|
+
activesupport (>= 2.3.6)
|
61
|
+
i18n (>= 0.4.0)
|
62
|
+
mime-types (~> 1.16)
|
63
|
+
treetop (~> 1.4.8)
|
64
|
+
mime-types (1.16)
|
65
|
+
money (3.6.1)
|
66
|
+
i18n (~> 0.4)
|
67
|
+
polyglot (0.3.1)
|
68
|
+
rack (1.2.1)
|
69
|
+
rack-mount (0.6.13)
|
70
|
+
rack (>= 1.0.0)
|
71
|
+
rack-test (0.5.7)
|
72
|
+
rack (>= 1.0)
|
73
|
+
rails (3.0.5)
|
74
|
+
actionmailer (= 3.0.5)
|
75
|
+
actionpack (= 3.0.5)
|
76
|
+
activerecord (= 3.0.5)
|
77
|
+
activeresource (= 3.0.5)
|
78
|
+
activesupport (= 3.0.5)
|
79
|
+
bundler (~> 1.0)
|
80
|
+
railties (= 3.0.5)
|
81
|
+
railties (3.0.5)
|
82
|
+
actionpack (= 3.0.5)
|
83
|
+
activesupport (= 3.0.5)
|
84
|
+
rake (>= 0.8.7)
|
85
|
+
thor (~> 0.14.4)
|
86
|
+
rake (0.8.7)
|
87
|
+
responders (0.6.2)
|
88
|
+
thor (0.14.6)
|
89
|
+
treetop (1.4.9)
|
90
|
+
polyglot (>= 0.3.1)
|
91
|
+
tzinfo (0.3.24)
|
92
|
+
will_paginate (2.3.15)
|
93
|
+
|
94
|
+
PLATFORMS
|
95
|
+
ruby
|
96
|
+
|
97
|
+
DEPENDENCIES
|
98
|
+
e9_crm!
|
99
|
+
e9_rails (~> 0.0.4)
|
100
|
+
e9_tags (~> 0.0.2)
|
101
|
+
has_scope
|
102
|
+
inherited_resources (~> 1.1.2)
|
103
|
+
money
|
104
|
+
rails (~> 3.0.0)
|
105
|
+
will_paginate
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
CRM Plugin for the e9 CMS
|
2
|
+
=========================
|
3
|
+
|
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
|
+
To use, add as a gem and install by running:
|
8
|
+
|
9
|
+
rails g e9_crm:install
|
10
|
+
|
11
|
+
Then modify the installed initializer as per your app, including
|
12
|
+
the controller module in your desired controllers, with the final
|
13
|
+
result looking something like this:
|
14
|
+
|
15
|
+
require 'e9_crm'
|
16
|
+
|
17
|
+
User.send :include, E9Crm::Backend::ActiveRecord
|
18
|
+
|
19
|
+
Rails.configuration.after_initialize do
|
20
|
+
[
|
21
|
+
MyFirstTrackedController,
|
22
|
+
MySecondTrackedController
|
23
|
+
].each {|c| c.send(:include, E9Crm::TrackingController) }
|
24
|
+
end
|
25
|
+
|
26
|
+
NOTE: A few assumptions are made:
|
27
|
+
---------------------------------
|
28
|
+
|
29
|
+
1. Your app has a "User" model
|
30
|
+
2. Your app has a controller method #current_user to return the
|
31
|
+
currently logged in user.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
class E9Crm::ContactEmailsController < E9Crm::ResourcesController
|
2
|
+
defaults
|
3
|
+
|
4
|
+
respond_to :js, :html
|
5
|
+
|
6
|
+
def create
|
7
|
+
create! do |success, failure|
|
8
|
+
success.html { redirect_to :admin_sent_email }
|
9
|
+
success.js { head :ok }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def build_resource
|
16
|
+
get_resource_ivar || begin
|
17
|
+
object = if params[resource_instance_name]
|
18
|
+
ContactEmail.new(params[resource_instance_name] || {})
|
19
|
+
else
|
20
|
+
ContactEmail.new_from_template(template, :from_email => current_user.email, :user_ids => params[:uids])
|
21
|
+
end
|
22
|
+
|
23
|
+
# we set the user_ids.blank? error right away signifiying a problem,
|
24
|
+
# as the record won't be valid if the user_ids weren't passed in params
|
25
|
+
if object.user_ids.blank?
|
26
|
+
object.errors.add(:user_ids, :blank)
|
27
|
+
end
|
28
|
+
|
29
|
+
set_resource_ivar(object)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# throw record_not_found if there's no template. #new requires email_template_id
|
34
|
+
# be passed in params (and also user_ids)
|
35
|
+
def template
|
36
|
+
@_template ||= EmailTemplate.find(params[:etid])
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class E9Crm::ContactMergesController < E9Crm::BaseController
|
2
|
+
before_filter :build_resources
|
3
|
+
|
4
|
+
def create
|
5
|
+
if @contact_a.update_attributes(params[:contact])
|
6
|
+
@contact_a.merge_and_destroy!(@contact_b)
|
7
|
+
redirect_to @contact_a
|
8
|
+
else
|
9
|
+
render :new
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def build_resources
|
16
|
+
@contact ||= Contact.new
|
17
|
+
@contact_a ||= Contact.find(params[:contact_a_id])
|
18
|
+
|
19
|
+
# NOTE lets see if this works
|
20
|
+
@contact_b ||= if params[:contact]
|
21
|
+
Contact.new(params[:contact])
|
22
|
+
else
|
23
|
+
Contact.find(params[:contact_b_id])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class E9Crm::ContactsController < E9Crm::ResourcesController
|
2
|
+
defaults :resource_class => Contact
|
3
|
+
|
4
|
+
include E9Tags::Controller
|
5
|
+
|
6
|
+
respond_to :js, :html
|
7
|
+
|
8
|
+
before_filter :determine_title, :only => :index
|
9
|
+
before_filter :load_user_ids, :only => :index
|
10
|
+
|
11
|
+
has_scope :search, :by_title, :by_company, :only => :index
|
12
|
+
has_scope :tagged, :only => :index, :type => :array
|
13
|
+
|
14
|
+
# record attributes templates js
|
15
|
+
skip_before_filter :authenticate_user!, :filter_access_filter, :only => :templates
|
16
|
+
before_filter :build_resource, :only => :templates
|
17
|
+
caches_action :templates
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def load_user_ids
|
22
|
+
@user_ids ||= begin
|
23
|
+
(User.primary.joins(:contact) & end_of_association_chain.scoped).all.map(&:id)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def determine_title
|
28
|
+
params.delete(:search) if params[:search].blank?
|
29
|
+
|
30
|
+
@index_title ||= if params[:tagged] && params[:search]
|
31
|
+
e9_t(:index_title_with_search_and_tags, :tagged => params[:tagged].join(' or '), :search => params[:search])
|
32
|
+
elsif params[:tagged]
|
33
|
+
e9_t(:index_title_with_tags, :tagged => params[:tagged].join(' or '))
|
34
|
+
elsif params[:search]
|
35
|
+
e9_t(:index_title_with_search, :search => params[:search])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_ordered_on
|
40
|
+
'first_name'
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_ordered_at
|
44
|
+
'ASC'
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class E9Crm::DealsController < E9Crm::ResourcesController
|
2
|
+
defaults :resource_class => Deal
|
3
|
+
|
4
|
+
filter_access_to :leads, :require => :read, :context => :admin
|
5
|
+
prepend_before_filter :set_leads_index_title, :only => :leads
|
6
|
+
|
7
|
+
has_scope :leads, :only => :leads, :default => true
|
8
|
+
has_scope :leads, :except => :leads, :default => false
|
9
|
+
|
10
|
+
def leads
|
11
|
+
index!
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def set_leads_index_title
|
17
|
+
@index_title = I18n.t(:index_title, :scope => 'e9.e9_crm.leads')
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class E9Crm::MenuOptionsController < E9Crm::ResourcesController
|
2
|
+
defaults :resource_class => MenuOption
|
3
|
+
include E9Rails::Controllers::Sortable
|
4
|
+
|
5
|
+
has_scope :options_for, :as => :key, :only => :index
|
6
|
+
|
7
|
+
# NOTE The reason this is set in a filter instead of just a default scope value
|
8
|
+
# is that it is used in the index view to add the key param to the new
|
9
|
+
# resource link
|
10
|
+
#
|
11
|
+
before_filter :ensure_default_fetch_key, :only => :index
|
12
|
+
|
13
|
+
def create
|
14
|
+
create! { collection_path(:key => resource.key) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def update
|
18
|
+
update! { collection_path(:key => resource.key) }
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def ensure_default_fetch_key
|
24
|
+
params[:key] ||= MenuOption::KEYS.sort.first
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class E9Crm::PageViewsController < E9Crm::ResourcesController
|
2
|
+
defaults :resource_class => PageView
|
3
|
+
belongs_to :campaign, :contact, :polymorphic => true
|
4
|
+
|
5
|
+
# NOTE association chain is prepended to ensure parent is loaded so other
|
6
|
+
# before filters can use collection_path, etc. Is there a better solution
|
7
|
+
# for this?
|
8
|
+
#
|
9
|
+
prepend_before_filter :association_chain
|
10
|
+
|
11
|
+
has_scope :until_time, :as => :until, :unless => 'params[:from].present?'
|
12
|
+
|
13
|
+
has_scope :from_time, :as => :from do |controller, scope, value|
|
14
|
+
if controller.params[:until]
|
15
|
+
scope.for_time_range(value, controller.params[:until])
|
16
|
+
else
|
17
|
+
scope.from_time(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class E9Crm::ResourcesController < E9Crm::BaseController
|
2
|
+
include E9Rails::Controllers::Orderable
|
3
|
+
include E9Rails::Helpers::ResourceErrorMessages
|
4
|
+
include E9Rails::Helpers::Pagination
|
5
|
+
|
6
|
+
inherit_resources
|
7
|
+
|
8
|
+
add_resource_breadcrumbs
|
9
|
+
|
10
|
+
def self.defaults(hash = {})
|
11
|
+
super(hash.reverse_merge(:route_prefix => nil))
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
create! { collection_path }
|
16
|
+
end
|
17
|
+
|
18
|
+
def update
|
19
|
+
update! { collection_path }
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
# NOTE parent is defined so it's always available, it will be overridden on controllers which have belongs_to routes
|
25
|
+
def parent; end
|
26
|
+
helper_method :parent
|
27
|
+
|
28
|
+
def add_index_breadcrumb
|
29
|
+
add_breadcrumb! @index_title || e9_t(:index_title), collection_path
|
30
|
+
end
|
31
|
+
|
32
|
+
def collection
|
33
|
+
get_collection_ivar || set_collection_ivar(end_of_association_chain.paginate(pagination_parameters))
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_ordered_on
|
37
|
+
'created_at'
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_ordered_dir
|
41
|
+
'DESC'
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module E9Crm::BaseHelper
|
2
|
+
|
3
|
+
##
|
4
|
+
# Field maps
|
5
|
+
#
|
6
|
+
|
7
|
+
def records_table_field_map(options = {})
|
8
|
+
options.symbolize_keys!
|
9
|
+
options.reverse_merge!(:class_name => resource_class.base_class.name.underscore)
|
10
|
+
|
11
|
+
base_map = {
|
12
|
+
:fields => { :id => nil },
|
13
|
+
:links => lambda {|r| [link_to_edit_resource(r), link_to_destroy_resource(r)] }
|
14
|
+
}
|
15
|
+
|
16
|
+
method_name = "records_table_field_map_for_#{options[:class_name]}"
|
17
|
+
|
18
|
+
if respond_to?(method_name)
|
19
|
+
base_map.merge! send(method_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
base_map
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
##
|
27
|
+
# Misc
|
28
|
+
#
|
29
|
+
|
30
|
+
def link_to_add_record_attribute(association_name)
|
31
|
+
link_to(
|
32
|
+
t(:add_record_attribute, :scope => :e9_crm),
|
33
|
+
'javascript:;',
|
34
|
+
:class => 'add-nested-association',
|
35
|
+
'data-association' => association_name
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def link_to_destroy_record_attribute
|
40
|
+
link_to(
|
41
|
+
t(:destroy_record_attribute, :scope => :e9_crm),
|
42
|
+
'javascript:;',
|
43
|
+
:class => 'destroy-nested-association'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def render_record_attribute_association(association_name, form, options = {})
|
48
|
+
options.symbolize_keys!
|
49
|
+
|
50
|
+
association = resource.send(association_name)
|
51
|
+
|
52
|
+
unless association.empty?
|
53
|
+
form.fields_for(association_name) do |f|
|
54
|
+
concat record_attribute_template(association_name, f, options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def record_attribute_template(association_name, builder, options = {})
|
60
|
+
options.symbolize_keys!
|
61
|
+
|
62
|
+
render({
|
63
|
+
:partial => options[:partial] || "e9_crm/record_attributes/#{association_name.to_s.singularize}",
|
64
|
+
:locals => { :f => builder }
|
65
|
+
})
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_associated_resource(association_name)
|
69
|
+
params_method = "#{association_name}_build_parameters"
|
70
|
+
build_params = resource_class.send(params_method) if resource_class.respond_to?(params_method)
|
71
|
+
resource.send(association_name).build(build_params || {})
|
72
|
+
end
|
73
|
+
|
74
|
+
def sortable_controller?
|
75
|
+
@_sortable_controller ||= controller.class.ancestors.member?(E9Rails::Controllers::Sortable)
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module E9Crm::CampaignsHelper
|
2
|
+
def records_table_map_for_campaign
|
3
|
+
{
|
4
|
+
:fields => {
|
5
|
+
:type => nil,
|
6
|
+
:name => nil,
|
7
|
+
:code => nil,
|
8
|
+
:affiliate_fee => proc {|r| v = r.affiliate_fee; Money === v ? v : 'n/a' },
|
9
|
+
:sales_fee => nil,
|
10
|
+
:status => proc {|r| resource_class.human_attribute_name(Campaign::Status::VALUES[r.status]) }
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module E9Crm::ContactMergesHelper
|
2
|
+
def contact_a(field_name)
|
3
|
+
@_contact_a_vals ||= {}
|
4
|
+
@_contact_a_vals[field_name] ||= merge_contact_val(@contact_a, field_name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def contact_b(field_name)
|
8
|
+
@_contact_b_vals ||= {}
|
9
|
+
@_contact_b_vals[field_name] ||= merge_contact_val(@contact_b, field_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def merge_contact_val(obj, field_name)
|
13
|
+
# return '' here rather than nil so inputs will have a value, otherwise checked
|
14
|
+
# with no value ends up being interpreted as "on"
|
15
|
+
obj.send(field_name) || ''
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module E9Crm::ContactsHelper
|
2
|
+
|
3
|
+
def link_to_contact_search(attribute, query, text = nil)
|
4
|
+
link_to(text || query, contacts_path(attribute => query), :class => "contact-search contact-#{attribute.to_s.dasherize}-search")
|
5
|
+
end
|
6
|
+
|
7
|
+
def contact_email_template_select_options
|
8
|
+
options_for_select( EmailTemplate.order('name').map {|e| [e.name, e.id] })
|
9
|
+
end
|
10
|
+
|
11
|
+
def contact_newsletter_select_options
|
12
|
+
options_for_select( UserEmail.pending.order('name').map {|e| [e.name, e.id] })
|
13
|
+
end
|
14
|
+
|
15
|
+
def records_table_field_map_for_contact
|
16
|
+
{
|
17
|
+
:fields => {
|
18
|
+
:avatar => proc {|r| },
|
19
|
+
:details => proc {|r| render('details', :record => r) }
|
20
|
+
},
|
21
|
+
|
22
|
+
:links => proc {|r|
|
23
|
+
[link_to_show_resource(r), link_to_edit_resource(r), link_to_destroy_resource(r)]
|
24
|
+
}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# An ad driven campaign.
|
2
|
+
#
|
3
|
+
# Unique from other campaigns in that their cost is derived from associated
|
4
|
+
# DatedCost records.
|
5
|
+
#
|
6
|
+
class AdvertisingCampaign < Campaign
|
7
|
+
has_many :dated_costs, :as => :costable
|
8
|
+
|
9
|
+
##
|
10
|
+
# The sum cost of this campaign
|
11
|
+
#
|
12
|
+
def cost
|
13
|
+
Money.new(dated_costs.sum(:cost))
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# An affiliate campaign
|
2
|
+
#
|
3
|
+
# Carries an affiliate fee (and sales fee)
|
4
|
+
#
|
5
|
+
class AffiliateCampaign < SalesCampaign
|
6
|
+
money_columns :affiliate_fee
|
7
|
+
belongs_to :affiliate
|
8
|
+
|
9
|
+
##
|
10
|
+
# The sum cost of this campaign
|
11
|
+
#
|
12
|
+
def cost
|
13
|
+
super + affiliate_fee
|
14
|
+
end
|
15
|
+
end
|