e9_crm 0.1.16 → 0.1.17
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/e9_crm/base_controller.rb +0 -2
- data/app/controllers/e9_crm/campaigns_controller.rb +1 -1
- data/app/controllers/e9_crm/contacts_controller.rb +1 -1
- data/app/controllers/e9_crm/deals_controller.rb +18 -0
- data/app/controllers/e9_crm/email_templates.controller.rb +4 -0
- data/app/controllers/e9_crm/resources_controller.rb +1 -0
- data/app/helpers/e9_crm/contacts_helper.rb +1 -0
- data/app/helpers/e9_crm/deals_helper.rb +23 -1
- data/app/models/campaign.rb +1 -0
- data/app/models/contact.rb +1 -1
- data/app/models/deal.rb +1 -1
- data/app/models/email_template.rb +7 -0
- data/app/models/no_campaign.rb +4 -4
- data/app/views/e9_crm/affiliate_campaigns/_form_inner.html.haml +1 -1
- data/app/views/e9_crm/campaigns/_table.html.haml +3 -3
- data/app/views/e9_crm/contact_merges/_form.html.haml +1 -1
- data/app/views/e9_crm/contacts/_sidebar.html.haml +4 -4
- data/app/views/e9_crm/contacts/_tag_table.html.haml +6 -7
- data/app/views/e9_crm/contacts/show.html.haml +2 -2
- data/app/views/e9_crm/deals/_form_inner.html.haml +25 -7
- data/app/views/e9_crm/deals/_leads_table.html.haml +3 -3
- data/app/views/e9_crm/deals/_table.html.haml +6 -5
- data/app/views/e9_crm/email_templates/_form_inner.html.haml +1 -1
- data/app/views/e9_crm/email_templates/select.html.haml +1 -2
- data/app/views/e9_crm/sales_campaigns/_form_inner.html.haml +1 -1
- data/app/views/record_attributes/_user.html.haml +1 -1
- data/config/locales/e9.en.yml +1 -2
- data/config/locales/en.yml +9 -5
- data/config/routes.rb +1 -1
- data/lib/e9_crm/version.rb +1 -1
- metadata +3 -3
@@ -12,6 +12,8 @@ class E9Crm::DealsController < E9Crm::ResourcesController
|
|
12
12
|
prepend_before_filter :set_leads_index_title, :only => :leads
|
13
13
|
prepend_before_filter :set_reports_index_title, :only => :reports
|
14
14
|
|
15
|
+
before_filter :prepop_deal_owner_contact, :only => [:new, :edit]
|
16
|
+
|
15
17
|
##
|
16
18
|
# All Scopes
|
17
19
|
#
|
@@ -103,6 +105,14 @@ class E9Crm::DealsController < E9Crm::ResourcesController
|
|
103
105
|
end
|
104
106
|
end
|
105
107
|
|
108
|
+
def prepop_deal_owner_contact
|
109
|
+
object = params[:id] ? resource : build_resource
|
110
|
+
|
111
|
+
if !object.owner && contact = current_user.contact
|
112
|
+
object.owner = contact
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
106
116
|
def set_leads_index_title
|
107
117
|
@index_title = I18n.t(:index_title, :scope => 'e9.e9_crm.leads')
|
108
118
|
end
|
@@ -114,4 +124,12 @@ class E9Crm::DealsController < E9Crm::ResourcesController
|
|
114
124
|
def ordered_if
|
115
125
|
%w(index leads reports).member? params[:action]
|
116
126
|
end
|
127
|
+
|
128
|
+
def default_ordered_on
|
129
|
+
'name'
|
130
|
+
end
|
131
|
+
|
132
|
+
def default_ordered_dir
|
133
|
+
'ASC'
|
134
|
+
end
|
117
135
|
end
|
@@ -3,6 +3,7 @@ class E9Crm::ResourcesController < E9Crm::BaseController
|
|
3
3
|
|
4
4
|
# NOTE depending on e9_base pagination (which should eventually use this module)
|
5
5
|
#include E9Rails::Helpers::Pagination
|
6
|
+
include E9::DestroyRestricted::Controller
|
6
7
|
|
7
8
|
# TODO implement role on e9_crm models?
|
8
9
|
#include E9::Roles::Controller
|
@@ -4,6 +4,7 @@ module E9Crm::ContactsHelper
|
|
4
4
|
@_contact_tags ||= begin
|
5
5
|
relation = Tagging.joins(:tag).select('distinct tags.name')
|
6
6
|
.where(:context => E9Tags.escape_context('users*'))
|
7
|
+
.order('tags.name ASC')
|
7
8
|
|
8
9
|
Tagging.connection.send(:select_values, relation.to_sql, 'Contact Tags Select')
|
9
10
|
end
|
@@ -32,7 +32,7 @@ module E9Crm::DealsHelper
|
|
32
32
|
def deal_owner_select_options
|
33
33
|
@_deal_owner_select_options ||= begin
|
34
34
|
options = Contact.deal_owners.all.map {|c| [c.name, c.id] }
|
35
|
-
options.unshift ['
|
35
|
+
options.unshift ['All Responsible', nil]
|
36
36
|
options_for_select(options)
|
37
37
|
end
|
38
38
|
end
|
@@ -69,4 +69,26 @@ module E9Crm::DealsHelper
|
|
69
69
|
|
70
70
|
options_for_select(options)
|
71
71
|
end
|
72
|
+
|
73
|
+
def deal_cost(deal)
|
74
|
+
campaign = deal.campaign
|
75
|
+
|
76
|
+
if campaign.blank?
|
77
|
+
0
|
78
|
+
else
|
79
|
+
c = campaign.non_leads.count
|
80
|
+
c > 0 ? campaign.cost.to_f / c : campaign.cost
|
81
|
+
end.to_money
|
82
|
+
end
|
83
|
+
|
84
|
+
def deal_contacts
|
85
|
+
@_eligible_responsible_contacts ||= begin
|
86
|
+
roles = E9::Roles.list.map(&:role).select {|r| r > 'user' && r < 'e9_user' }
|
87
|
+
User.includes(:contact).for_roles(roles).all.map(&:contact).compact
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def deal_contacts_array
|
92
|
+
deal_contacts.map {|c| [c.name, c.id] }.sort_by {|name, id| name.upcase }
|
93
|
+
end
|
72
94
|
end
|
data/app/models/campaign.rb
CHANGED
@@ -13,6 +13,7 @@ class Campaign < ActiveRecord::Base
|
|
13
13
|
has_many :lost_deals, :class_name => 'Deal', :conditions => ['deals.status = ?', Deal::Status::Lost]
|
14
14
|
has_many :pending_deals, :class_name => 'Deal', :conditions => ['deals.status = ?', Deal::Status::Pending]
|
15
15
|
has_many :leads, :class_name => 'Deal', :conditions => ['deals.status = ?', Deal::Status::Lead]
|
16
|
+
has_many :non_leads, :class_name => 'Deal', :conditions => ['deals.status != ?', Deal::Status::Lead]
|
16
17
|
has_many :page_views, :inverse_of => :campaign, :dependent => :nullify
|
17
18
|
|
18
19
|
# only advertising campaigns use this association
|
data/app/models/contact.rb
CHANGED
data/app/models/deal.rb
CHANGED
data/app/models/no_campaign.rb
CHANGED
@@ -7,4 +7,4 @@
|
|
7
7
|
= f.collection_select :affiliate_id, Contact.affiliates.ordered.all, :id, :name, {:prompt => true}, :id => 'campaign_affiliate_id'
|
8
8
|
.field
|
9
9
|
= help_label f, :affiliate_fee
|
10
|
-
= f.text_field :affiliate_fee
|
10
|
+
= f.text_field :affiliate_fee, :value => f.object.affiliate_fee.to_s
|
@@ -2,8 +2,8 @@
|
|
2
2
|
%thead
|
3
3
|
%tr
|
4
4
|
%th= orderable_column_link(:type)
|
5
|
-
%th= orderable_column_link(:name)
|
6
5
|
%th= orderable_column_link('campaign_group_name', :campaign_group)
|
6
|
+
%th= orderable_column_link(:name)
|
7
7
|
%th= orderable_column_link(:code)
|
8
8
|
%th= orderable_column_link(:affiliate_fee)
|
9
9
|
%th= orderable_column_link(:sales_fee)
|
@@ -17,10 +17,10 @@
|
|
17
17
|
%tr{:id => "ids_#{record.id}", :class => cycle('odd', 'even')}
|
18
18
|
%td.record-type
|
19
19
|
= record.type[/(.*)Campaign/, 1]
|
20
|
-
%td.record-name
|
21
|
-
= record.name
|
22
20
|
%td.record-campaign-group
|
23
21
|
= record.campaign_group_name || e9_t(:no_group, :scope => 'e9_crm.campaigns')
|
22
|
+
%td.record-name
|
23
|
+
= record.name
|
24
24
|
%td.record-code
|
25
25
|
= display_campaign_code(record.code)
|
26
26
|
%td.record-affiliate-fee
|
@@ -25,14 +25,14 @@
|
|
25
25
|
%label= Contact.human_attribute_name(:website_attributes)
|
26
26
|
- resource.website_attributes.each do |website_attribute|
|
27
27
|
.contact-website
|
28
|
-
|
29
|
-
= link_to(website_attribute.to_s, website_attribute.to_s, :rel => "external nofollow")
|
28
|
+
= website_attribute.to_s
|
30
29
|
|
31
30
|
- if resource.address_attributes.any?
|
32
31
|
.contact-addresses
|
33
32
|
%label= Contact.human_attribute_name(:address_attributes)
|
34
33
|
- resource.address_attributes.each do |address_attribute|
|
35
34
|
.contact-address
|
36
|
-
.address
|
35
|
+
.address
|
36
|
+
= address_attribute.to_s
|
37
37
|
.actions
|
38
|
-
=
|
38
|
+
= address_attribute.link
|
@@ -1,9 +1,8 @@
|
|
1
1
|
- tagged_params = Array.wrap(params[:tagged])
|
2
|
+
|
2
3
|
%label= t(:tags_name, :scope => :e9_tags)
|
3
|
-
.
|
4
|
-
- contact_tags.
|
5
|
-
%
|
6
|
-
|
7
|
-
|
8
|
-
= label_tag(tag_id, tag)
|
9
|
-
= check_box_tag('tagged[]', tag, tagged_params.member?(tag), :id => tag_id)
|
4
|
+
%ul.tags
|
5
|
+
- contact_tags.each do |tag|; tag_id = "tagged-#{tag.downcase.dasherize}"
|
6
|
+
%li.tag
|
7
|
+
= label_tag(tag_id, tag)
|
8
|
+
= check_box_tag('tagged[]', tag, tagged_params.member?(tag), :id => tag_id)
|
@@ -14,11 +14,11 @@
|
|
14
14
|
- if (tags = resource.tags(:show_all => true)).present?
|
15
15
|
.contact-tags
|
16
16
|
%label #{Tag.model_name.human.pluralize}:
|
17
|
-
= contact_tag_list(tags)
|
17
|
+
= contact_tag_list(tags.sort)
|
18
18
|
|
19
19
|
.contact-info
|
20
20
|
%label #{Contact.human_attribute_name(:info)}:
|
21
|
-
=
|
21
|
+
= resource.info.present? && k(resource.info) || t(:none)
|
22
22
|
|
23
23
|
- if company = resource.company
|
24
24
|
.contact-company
|
@@ -12,23 +12,41 @@
|
|
12
12
|
= f.label :category
|
13
13
|
= f.select :category, MenuOption.options_for('Deal Category'), :include_blank => 'No Category'
|
14
14
|
.field
|
15
|
-
= f
|
16
|
-
= f.collection_select :campaign_id, Campaign.ordered.all, :id, :to_s, {:prompt => true}, :id => 'deal_campaign_select'
|
17
|
-
.field
|
18
|
-
= f.label :info
|
15
|
+
= help_label(f, :info, :key => :markdown_help, :header => 'Markdown Help')
|
19
16
|
= f.text_area :info
|
20
17
|
.field
|
21
18
|
= f.label :value, nil, :class => :req
|
22
19
|
= f.text_field :value
|
23
20
|
.field.select
|
24
|
-
= f.label :
|
25
|
-
= f.collection_select :
|
21
|
+
= f.label :campaign, :for => 'deal_campaign_select'
|
22
|
+
= f.collection_select :campaign_id, Campaign.ordered.all, :id, :to_s, {:prompt => true}, :id => 'deal_campaign_select'
|
23
|
+
.field.select
|
24
|
+
= f.label :status
|
25
|
+
= f.select :status, Deal::Status::OPTIONS[1..-1]
|
26
26
|
.field.select
|
27
27
|
= f.label :contacts
|
28
|
-
%input#contact_autocomplete.list{:type => 'text', 'data-values' =>
|
28
|
+
%input#contact_autocomplete.list{:type => 'text', 'data-values' => resource.contact_ids.join(','), 'data-iname' => resource_instance_name, 'data-field' => '[contact_ids]', :id => 'deal_contacts'}
|
29
29
|
%ul.select
|
30
30
|
- f.object.contacts.each do |contact|
|
31
31
|
%li.ui-state-default
|
32
32
|
%span.content= contact.name
|
33
33
|
%input{:type => :hidden, :name => "contact[contact_ids][]", :value => contact.id}
|
34
34
|
%a{:class => :remove, :title => "Remove", :alt => "Remove"} Remove
|
35
|
+
.field.select
|
36
|
+
= f.label :owner
|
37
|
+
= f.select :contact_id, deal_contacts_array, { :prompt => true }, :id => :deal_owner
|
38
|
+
.field
|
39
|
+
Created At:
|
40
|
+
= l(resource.created_at)
|
41
|
+
.field
|
42
|
+
Closed At:
|
43
|
+
= resource.closed_at ? l(resource.closed_at) : 'n/a'
|
44
|
+
.field
|
45
|
+
Campaign Cost:
|
46
|
+
= resource.campaign.try(:cost) || 0
|
47
|
+
.field
|
48
|
+
Campaign Deal Count:
|
49
|
+
= resource.campaign ? resource.campaign.non_leads.count : 0
|
50
|
+
.field
|
51
|
+
Cost:
|
52
|
+
= deal_cost(resource)
|
@@ -6,7 +6,7 @@
|
|
6
6
|
%th= orderable_column_link(:campaign_code)
|
7
7
|
%th= orderable_column_link(:lead_name)
|
8
8
|
%th= orderable_column_link(:lead_email)
|
9
|
-
%th= orderable_column_link(:
|
9
|
+
%th= orderable_column_link(:info)
|
10
10
|
%th= t(:actions)
|
11
11
|
%tbody
|
12
12
|
- if collection.empty?
|
@@ -25,8 +25,8 @@
|
|
25
25
|
= record.lead_name
|
26
26
|
%td.record-lead-email
|
27
27
|
= record.lead_email
|
28
|
-
%td.record-
|
29
|
-
= record.
|
28
|
+
%td.record-info
|
29
|
+
= record.info
|
30
30
|
%td.actions
|
31
31
|
- if record.contacts.present?
|
32
32
|
= link_to_show_resource(record.contacts.first)
|
@@ -25,10 +25,11 @@
|
|
25
25
|
= record.category
|
26
26
|
%td.record-owner
|
27
27
|
= record.owner_name
|
28
|
-
%td.record-value
|
28
|
+
%td.record-value.num
|
29
29
|
- dat[:value] << record.value
|
30
|
-
= record.value
|
31
|
-
%td.
|
30
|
+
= record.value.to_money.format
|
31
|
+
%td.links
|
32
|
+
= link_to_show_resource(record)
|
32
33
|
= link_to_edit_resource(record)
|
33
34
|
= link_to_destroy_resource(record)
|
34
35
|
|
@@ -36,8 +37,8 @@
|
|
36
37
|
%tr{:class => 'record-totals'}
|
37
38
|
%td.record-totals-label{:colspan => 4}
|
38
39
|
#{t(:total)}:
|
39
|
-
%td.record-totals
|
40
|
-
= dat[:value].sum
|
40
|
+
%td.record-totals.num
|
41
|
+
= dat[:value].sum.to_money.format
|
41
42
|
%td
|
42
43
|
|
43
44
|
- if @controller.should_paginate_index
|
@@ -1,5 +1,4 @@
|
|
1
|
-
=
|
2
|
-
= form_tag email_templates_path, :id => "email_templates_select", :method => :get do
|
1
|
+
= form_tag email_templates_path, :class => "email-template-sel", :method => :get do
|
3
2
|
= hidden_field_tag "contact_id", params[:contact_id]
|
4
3
|
= hidden_field_tag "user_id", params[:user_id]
|
5
4
|
= select_tag "id", options_for_select(collection.map {|e| [e.name, e.id] })
|
data/config/locales/e9.en.yml
CHANGED
data/config/locales/en.yml
CHANGED
@@ -12,16 +12,12 @@ en:
|
|
12
12
|
total: Total
|
13
13
|
totals: Totals
|
14
14
|
view: View
|
15
|
+
save: Save
|
15
16
|
|
16
17
|
e9_crm:
|
17
18
|
add_record_attribute: Add
|
18
19
|
destroy_record_attribute: Remove
|
19
20
|
|
20
|
-
# activemodel translation looks to %{i18n_scope}.attributes.%{model_name}.%{attribute}
|
21
|
-
# then simply attributes.%{attribute}, dropping i18n_scope, e.g "activerecord"
|
22
|
-
attributes:
|
23
|
-
markdown_help: "You can style the text in this field using the Markdown syntax as follows:\n\nA line break is created by putting 2 spaces\n\nat the end of the line above and then a return.\n\nA paragraph is created by putting a blank line between the first paragraph and the second paragraph.\n\nThis is the start of the next paragraph.\n\n*italics*\n\n**bold**\n\n***bold and italic text***\n\n* Item in a bulleted list\n\t* A sub-item, indented with 4 spaces\n* Another item in a bulleted list\n\n1. Item in numbered list\n2. Another Item in numbered list\n3. Another Item in numbered list\n\n# First-level heading\n\n## Second-level heading\n\n### Third-level heading\n\n#### Fourth-level heading\n\n> This is a blockquote.\n> Blockquote with hard wrap\n>\n> This is the second paragraph in the blockquote.\n>\n> ## This is an H2 in a blockquote\n\n[This is a link](http://www.google.com \"Google\")\n\n![Image Alt Text](image url \"Image Title\")\n\n--- Horizontal rules are created by 3 hyphens\n\nIf you need to actually render the following characters AND they are NOT rendering, place a backslash before the character like \*italics\* will actually render with the asterisks instead of italicizing the word.\n\n\\\tbackslash\n*\tasterisk\n_\tunderscore\n{}\tcurly braces\n[]\tsquare brackets\n()\tparentheses\n#\thash mark\n+\tplus sign\n-\tminus sign (hyphen)\n.\tdot\n!\texclamation mark"
|
24
|
-
|
25
21
|
activerecord:
|
26
22
|
titles:
|
27
23
|
show: 'Show %{model}'
|
@@ -119,6 +115,14 @@ en:
|
|
119
115
|
no_leads: 'There are no leads associated with this contact.'
|
120
116
|
company:
|
121
117
|
info: Background Information
|
118
|
+
email_template:
|
119
|
+
text_body_help: |
|
120
|
+
<h3>Variables:</h3>
|
121
|
+
<p>You can insert the following to render variable data in the field</p>
|
122
|
+
<p>
|
123
|
+
{{contact.first_name}}<br/>
|
124
|
+
{{recipient.email}}<br/>
|
125
|
+
</p>
|
122
126
|
deal:
|
123
127
|
info: Details
|
124
128
|
lead_email: Email
|
data/config/routes.rb
CHANGED
data/lib/e9_crm/version.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 17
|
9
|
+
version: 0.1.17
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Travis Cox
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-09-
|
17
|
+
date: 2011-09-09 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|