e9_crm 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,9 +14,15 @@ class E9Crm::DealsController < E9Crm::ResourcesController
14
14
  # Index/Reports Scopes
15
15
  #
16
16
 
17
- has_scope :leads, :only => :leads, :default => true
18
- has_scope :leads, :except => [:leads, :reports], :default => false
17
+ # NOTE default => 'true' only exists to ensure this scope is called
18
+ has_scope :only_leads, :only => :leads, :default => 'true' do |controller, scope|
19
+ scope.leads(true)
20
+ end
19
21
 
22
+ # NOTE default => 'false' only exists to ensure this scope is called
23
+ has_scope :no_leads, :except => [:leads, :reports], :default => 'false' do |controller, scope|
24
+ scope.leads(false)
25
+ end
20
26
 
21
27
  ##
22
28
  # Reports scopes
@@ -42,7 +48,6 @@ class E9Crm::DealsController < E9Crm::ResourcesController
42
48
  end
43
49
  end
44
50
 
45
-
46
51
  ##
47
52
  # Actions
48
53
  #
@@ -63,7 +68,9 @@ class E9Crm::DealsController < E9Crm::ResourcesController
63
68
  if params[:action] == 'reports'
64
69
  end_of_association_chain.all
65
70
  else
66
- end_of_association_chain.paginate(pagination_parameters)
71
+ end_of_association_chain
72
+ .joins("left outer join contacts on contacts.id = deals.contact_id")
73
+ .select("deals.*, contacts.first_name owner_name")
67
74
  end
68
75
  )
69
76
  end
@@ -1,16 +1,16 @@
1
1
  module E9Crm::DealsHelper
2
- def records_table_field_map_for_deal
3
- {
4
- :fields => {
5
- :created_at => nil,
6
- :offer => nil,
7
- :campaign => nil
8
- },
9
-
10
- :links => proc {|r|
11
- []
12
- }
13
- }
2
+ def deal_contact_select_options
3
+ @_deal_contact_select_options ||= begin
4
+ contacts = Contact.available_to_deal(resource)
5
+
6
+ options = contacts.map {|contact| [contact.name, contact.id] }
7
+ options.unshift ['Add Contact', nil]
8
+ options_for_select options
9
+ end
10
+ end
11
+
12
+ def deal_contact_select
13
+ select_tag 'contacts_ids', deal_contact_select_options
14
14
  end
15
15
 
16
16
  def deal_date_select_options(ending_month = false)
@@ -13,6 +13,8 @@ class Contact < ActiveRecord::Base
13
13
  # Associations
14
14
  #
15
15
  belongs_to :company
16
+ has_many :owned_deals, :class_name => 'Deal'
17
+ has_and_belongs_to_many :associated_deals, :class_name => 'Deal'
16
18
 
17
19
  has_many :users, :inverse_of => :contact, :dependent => :nullify do
18
20
 
@@ -158,6 +160,20 @@ class Contact < ActiveRecord::Base
158
160
  end
159
161
  }
160
162
 
163
+ def self.available_to_deal(deal)
164
+ return all unless deal.persisted?
165
+
166
+ sql = <<-SQL
167
+ SELECT distinct contacts.* FROM `contacts`
168
+ LEFT OUTER JOIN `contacts_deals`
169
+ ON `contacts_deals`.`contact_id` = `contacts`.`id`
170
+ WHERE (`contacts_deals`.`deal_id` IS NULL
171
+ OR `contacts_deals`.`deal_id` != #{deal.id})
172
+ SQL
173
+
174
+ find_by_sql(sql)
175
+ end
176
+
161
177
  #
162
178
  # Carrierwave
163
179
  #
data/app/models/deal.rb CHANGED
@@ -9,13 +9,20 @@ class Deal < ActiveRecord::Base
9
9
  belongs_to :tracking_cookie, :inverse_of => :deals
10
10
  belongs_to :offer, :inverse_of => :deals
11
11
 
12
+ belongs_to :owner, :class_name => 'Contact', :foreign_key => :contact_id
13
+ has_and_belongs_to_many :contacts
14
+
12
15
  money_columns :value
16
+
17
+ validates :name, :presence => true
13
18
  validates :value, :numericality => true
14
19
 
15
20
  %w(total_value average_value total_cost average_cost).each do |money_column|
16
21
  class_eval("def #{money_column}; (r = read_attribute(:#{money_column})) && Money.new(r) end")
17
22
  end
18
23
 
24
+ delegate :name, :to => :owner, :prefix => true, :allow_nil => true
25
+
19
26
  scope :reports, lambda {
20
27
  select_sql = <<-SELECT.gsub(/\s+/, ' ')
21
28
  campaigns.id campaign_id,
@@ -120,7 +127,6 @@ class Deal < ActiveRecord::Base
120
127
  scope :won, lambda {|reverse=true| column_eq(:status, Status::Won, !reverse) }
121
128
  scope :lost, lambda {|reverse=true| column_eq(:status, Status::Lost, !reverse) }
122
129
 
123
-
124
130
  protected
125
131
 
126
132
  def method_missing(method_name, *args)
@@ -30,4 +30,8 @@ class MenuOption < ActiveRecord::Base
30
30
  def self.fetch_values(key)
31
31
  connection.send(:select_values, options_for(key).order(:position).project('value').to_sql, 'Menu Option Select')
32
32
  end
33
+
34
+ def to_s
35
+ value
36
+ end
33
37
  end
@@ -1,4 +1,3 @@
1
- - contact_ids = collection.map(&:id)
2
1
  .toolbar
3
2
  .toolbar-left
4
3
  = form_tag(resource_class, :method => :get, :id => 'contact_search_form') do
@@ -12,7 +11,7 @@
12
11
  = tag
13
12
  = hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_email_uids'
14
13
  = submit_tag e9_t(:send_email_template), :name => nil
15
- - if (tag = contact_email_template_select_tag).present?
14
+ - if (tag = contact_newsletter_select_tag).present?
16
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
17
16
  = tag
18
17
  = hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_newsletter_uids'
@@ -0,0 +1,16 @@
1
+ - field_map = local_assigns[:field_map] || records_table_field_map
2
+
3
+ %table.records
4
+ %tbody
5
+ - if collection.empty?
6
+ %tr
7
+ %td{:colspan => field_map[:fields].length + 1}= e9_t(:no_records_text)
8
+ - else
9
+ - collection.each do |record|
10
+ %tr{:id => "ids_#{record.id}", :class => cycle('odd', 'even')}
11
+ - field_map[:fields].each do |key, value|
12
+ %td{:class => "record-#{key.to_s.dasherize}"}
13
+ = value.respond_to?(:call) ? value.call(record) : record.send(key)
14
+ %td.links
15
+ - field_map[:links][record].each do |link|
16
+ = link
@@ -1,12 +1,38 @@
1
1
  = title (@index_title || e9_t(:index_title))
2
2
 
3
- #index-header
4
- = render 'header'
3
+ #index-body
4
+ #records_table
5
+ = render 'table', :resources => collection
6
+ = render 'footer'
5
7
 
6
- #contact-tag-list
7
- = render 'tag_table'
8
+ #index-sidebar
9
+ .actions
10
+ = link_to_new_resource(Contact)
11
+ = link_to_new_resource(Company)
8
12
 
9
- #records_table
10
- = render 'table', :resources => collection
13
+ -# Email actions (template, newsletter)
14
+ - etag, ntag = contact_email_template_select_tag, contact_newsletter_select_tag
15
+ - if [etag, ntag].any?(&:present?)
16
+ %fieldset
17
+ %legend= e9_t(:email_actions_legend)
18
+ - if etag
19
+ = 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
20
+ = etag
21
+ = hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_email_uids'
22
+ = submit_tag e9_t(:send_email_template), :name => nil
23
+ - if ntag
24
+ = 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
25
+ = ntag
26
+ = hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_newsletter_uids'
27
+ = submit_tag e9_t(:send_email_newsletter), :name => nil
11
28
 
12
- = render 'footer'
29
+ -# Search filter options
30
+ %fieldset
31
+ %legend= e9_t(:search_options_legend)
32
+ = form_tag(resource_class, :method => :get, :id => 'contact_search_form') do
33
+ = label_tag 'contact_search_field', t(:search)
34
+ = text_field_tag 'search', params[:search], :id => 'contact_search_field'
35
+ = submit_tag t(:go), :name => nil
36
+ = render 'tag_table'
37
+ .actions
38
+ = submit_tag t(:clear), :name => nil, :id => 'contact_search_clear'
@@ -19,6 +19,6 @@
19
19
  = google_search_link(company.name)
20
20
  = google_news_link(company.name)
21
21
  - if company.info.present?
22
- = contact_simple_format(text)
22
+ = contact_simple_format(company.info)
23
23
  .contact-sidebar
24
24
  = render 'sidebar'
File without changes
@@ -1,5 +1,27 @@
1
- - resource.attributes.each_pair do |field, value|
2
- - next if ['id', 'created_at', 'updated_at'].include?(field)
3
- .field
4
- = f.label field
5
- = f.text_field field
1
+ .actions
2
+ = link_to_destroy_resource(resource, :remote => false) if resource.persisted?
3
+ .field
4
+ = f.label :name, nil, :class => :req
5
+ = f.text_field :name
6
+ .field
7
+ = f.label :info
8
+ = f.text_area :info
9
+ .field
10
+ = f.label :value, nil, :class => :req
11
+ = f.text_field :value
12
+ .field.select
13
+ = f.label :contacts
14
+ %select.list{'data-iname' => resource_instance_name, 'data-field' => '[contact_ids]'}
15
+ = deal_contact_select_options
16
+ %ul.select
17
+ - f.object.contacts.each do |contact|
18
+ %li
19
+ %span= contact.name
20
+ %input{:type => :hidden, :name => "contact[contact_ids][]", :value => contact.id}
21
+ %a{:class => :remove, :title => "Remove", :alt => "Remove"} Remove
22
+ .field.select
23
+ = f.label :owner
24
+ = f.collection_select :contact_id, Contact.all, :id, :name
25
+ .field.select
26
+ = f.label :category
27
+ = f.select :category, MenuOption.options_for('Deal Category'), :include_blank => 'No Category'
@@ -0,0 +1,41 @@
1
+ %table.records
2
+ %thead
3
+ %tr
4
+ %th= orderable_column_link(:name)
5
+ %th= orderable_column_link(:status)
6
+ %th= orderable_column_link(:category)
7
+ %th= orderable_column_link('owner_name', :owner)
8
+ %th= orderable_column_link(:value)
9
+ %th= t(:actions)
10
+ %tbody
11
+ -# prepare a hash to store the accumulated row data for calculations
12
+ - dat = Hash.new {|k,v| k[v] = [] }
13
+
14
+ - if collection.empty?
15
+ %tr
16
+ %td{:colspan => 6}= e9_t(:no_records_text, :scope => 'e9_crm.deals')
17
+ - else
18
+ - collection.each do |record|
19
+ %tr{:id => "ids_#{record.id}", :class => cycle('odd', 'even')}
20
+ %td.record-name
21
+ = record.name
22
+ %td.record-status
23
+ = record.status
24
+ %td.record-category
25
+ = record.category
26
+ %td.record-owner
27
+ = record.owner_name
28
+ %td.record-value
29
+ - dat[:value] << record.value
30
+ = record.value
31
+ %td.actions
32
+ = link_to_edit_resource(record)
33
+ = link_to_destroy_resource(record)
34
+
35
+ %tfooter
36
+ %tr{:class => 'record-totals'}
37
+ %td.record-totals-label{:colspan => 4}
38
+ #{t(:total)}:
39
+ %td.record-totals
40
+ = dat[:value].sum
41
+ %td
@@ -18,6 +18,8 @@ en:
18
18
  send_email_newsletter: Send Newsletter
19
19
  contact_newsletter_confirmation: "The system will send the newsletter to all of the selected contacts (%{count}) if they are subscribed to receieve email. Are you sure you want to proceed?"
20
20
  no_contacts_notification: "You cannot send an email with no recipients!"
21
+ email_actions_legend: Email Actions
22
+ search_options_legend: Search Filters
21
23
  contact_merges:
22
24
  new_title: Merge Contacts
23
25
  no_value: (No Value)
@@ -1,14 +1,16 @@
1
1
  en:
2
+ actions: Actions
2
3
  clear: Clear
4
+ edit_dated_costs: Edit Costs
3
5
  go: Go
4
- search: Search
5
- view: View
6
- none: None
7
- totals: Totals
8
6
  inline_help_link: '[?]'
9
- edit_dated_costs: Edit Costs
10
- news: News
11
7
  map: Map
8
+ news: News
9
+ none: None
10
+ search: Search
11
+ total: Total
12
+ totals: Totals
13
+ view: View
12
14
 
13
15
  e9_crm:
14
16
  add_record_attribute: Add
@@ -1,3 +1,3 @@
1
1
  module E9Crm
2
- VERSION = '0.1.6'
2
+ VERSION = '0.1.7'
3
3
  end
@@ -1,27 +1,15 @@
1
1
  jQuery(function($) {
2
- var selector_prefix = 'body.controller-e9-crm-contacts',
3
- $selector = $(selector_prefix);
4
2
 
5
- $.fn.exclusiveCheck = function() {
6
- var selector = $(this);
7
- return this.each(function(i) {
8
- $(this).click(function(e) {
9
- var clicked = this;
10
- if (this.checked) {
11
- selector.each(function() {
12
- if (this != clicked) this.checked = false;
13
- });
14
- }
15
- });
16
- });
17
- }
3
+ $('.dated-costs > .actions a').bind('ajax:success', function(e, data, status, xhr) {
4
+ $(data).insertBefore($(this).closest('.actions'));
5
+ });
18
6
 
19
7
  /*
20
8
  * A function might exist for this already, but basically this stores the query variables
21
9
  * in a hash when the page loads for later re-use/modification.
22
10
  */
23
- $.query = (function() {
24
- var qs = document.location.search;
11
+ function query_to_hash(qs) {
12
+ if (!qs) qs = document.location.search;
25
13
 
26
14
  if (!qs.length) return {};
27
15
 
@@ -44,7 +32,118 @@ jQuery(function($) {
44
32
  }
45
33
 
46
34
  return params;
47
- })();
35
+ }
36
+
37
+ $.query = query_to_hash();
38
+
39
+ $.fn.bindSelectChange = function(callback) {
40
+ this.bind($.browser.msie ? 'propertychange' : 'change', callback);
41
+ }
42
+
43
+ $("#campaign_code_field input").keyup(function() {
44
+ $.event.trigger('campaign_code_change', [$(this).val()]);
45
+ });
46
+
47
+ $("#campaign_code_hint").bind("campaign_code_change", function(e, code) {
48
+ $(this).html(function(i, v) {
49
+ return v.replace(/=(.*)$/, '='+code);
50
+ });
51
+ });
52
+
53
+ $('.ordered-column a').live('click', function(e) {
54
+ e.preventDefault();
55
+
56
+ var $this = $(this),
57
+ href = $this.attr('href'),
58
+ qs = href.match(/\?.*$/)[0];
59
+
60
+ var qh = qs && query_to_hash(qs) || {};
61
+
62
+ $.extend($.query, {
63
+ order : qh.order,
64
+ sort : qh.sort
65
+ });
66
+
67
+ submit_with_query();
68
+ });
69
+
70
+ $("#campaign_search_form").each(function(i, el) {
71
+ var
72
+ $form = $(el),
73
+ $st = $(el).find('select[name=type]'),
74
+ $sg = $(el).find('select[name=group]'),
75
+ $sa = $(el).find('select[name=active]'),
76
+ $sf = $(el).find('select[name=from]'),
77
+ $su = $(el).find('select[name=until]')
78
+ ;
79
+
80
+ $st.val($.query.type);
81
+ $sg.val($.query.group);
82
+ $sa.val($.query.active);
83
+ $sf.val($.query.from);
84
+ $su.val($.query.until);
85
+
86
+ $('select', $form).bindSelectChange(function() {
87
+ var opts = {}, v;
88
+ if (v = $st.val()) {
89
+ opts['type'] = v;
90
+ } else {
91
+ delete $.query['type'];
92
+ }
93
+ if (v = $sg.val()) {
94
+ opts['group'] = v;
95
+ } else {
96
+ delete $.query['group'];
97
+ }
98
+ if (v = $sa.val()) {
99
+ opts['active'] = v;
100
+ } else {
101
+ delete $.query['active'];
102
+ }
103
+ if (v = $sf.val()) {
104
+ opts['from'] = v;
105
+ } else {
106
+ delete $.query['from'];
107
+ }
108
+ if (v = $su.val()) {
109
+ opts['until'] = v;
110
+ } else {
111
+ delete $.query['until'];
112
+ }
113
+ $.extend($.query, opts);
114
+ submit_with_query();
115
+ });
116
+ });
117
+
118
+ $("#new_campaign_form").each(function(i, el) {
119
+ var $form = $(el);
120
+
121
+ $('select', $form).bindSelectChange(function() {
122
+ var $this = $(this);
123
+
124
+ $form.attr("action", function(i, val) {
125
+ return val.replace(/\/\w*\/new$/, '/'+$this.val()+'/new');
126
+ });
127
+ });
128
+ });
129
+
130
+ var selector_prefix = 'body.controller-e9-crm-contacts',
131
+ $selector = $(selector_prefix);
132
+
133
+ $.fn.exclusiveCheck = function() {
134
+ var selector = $(this);
135
+ return this.each(function(i) {
136
+ $(this).click(function(e) {
137
+ var clicked = this;
138
+ if (this.checked) {
139
+ selector.each(function() {
140
+ if (this != clicked) this.checked = false;
141
+ });
142
+ }
143
+ });
144
+ });
145
+ }
146
+
48
147
 
49
148
  /*
50
149
  * The status of "primary" for a User login is stored on the individual records, but must be exlcusive in
@@ -57,33 +156,33 @@ jQuery(function($) {
57
156
  $('.nested-association input[type=radio][name$="[primary]"]', $(selector_prefix)).exclusiveCheck();
58
157
  })();
59
158
 
60
- /**
159
+ /*
61
160
  * Adds a new nested assocation. Depends on the nested association
62
161
  * js templates being loaded.
63
162
  */
64
163
  $('a.add-nested-association').click(function(e) {
65
164
  e.preventDefault();
66
165
 
67
- var $this = $(this),
68
- $parent = $this.closest('.nested-associations'),
69
- template,
70
- index;
166
+ var $this = $(this), template;
71
167
 
168
+ // get the template for this attribute type
72
169
  try {
73
170
  template = E9CRM.js_templates[this.getAttribute('data-association')];
74
171
  } catch(e) { return }
75
172
 
173
+ // sub in the current index and increment it
76
174
  template = template.replace(
77
175
  new RegExp(E9CRM.js_templates.start_child_index, 'g'),
78
176
  ++E9CRM.js_templates.current_child_index
79
177
  );
80
178
 
81
- $(template).appendTo($parent);
179
+ // and insert the new template before this link
180
+ $(template).insertBefore($this);
82
181
 
83
182
  exclusifyEmailRadios();
84
183
  });
85
184
 
86
- /**
185
+ /*
87
186
  * Effectively destroys an added nested association, removing the container
88
187
  * the association is not persisted, or hiding it and setting the _destroy
89
188
  * parameter for the association if it is.
@@ -91,17 +190,22 @@ jQuery(function($) {
91
190
  $('a.destroy-nested-association').live('click', function(e) {
92
191
  e.preventDefault();
93
192
 
193
+ // grab the parent nested-association and attempt to get its hidden
194
+ // 'destroy' input if it exists.
94
195
  var $parent = $(this).closest('.nested-association').hide(),
95
196
  $destro = $parent.find('input[id$=__destroy]');
96
197
 
97
- if ($destro.length) {
98
- $destro.val('1');
99
- } else {
100
- $parent.remove();
101
- }
198
+ // If a in input ending in __destroy was found it means that this is a
199
+ // persisted record. Set that input's value to '1' so it will be destroyed
200
+ // on record commit.
201
+ if ($destro.length) { $destro.val('1'); }
202
+
203
+ // otherwise this record was created locally and has not been saved, so
204
+ // simply remove it.
205
+ else { $parent.remove(); }
102
206
  });
103
207
 
104
- var filter_contacts = function(data) {
208
+ var submit_with_query = function(data) {
105
209
  $.ajax({
106
210
  dataType: 'script',
107
211
  url: window.location.pathname,
@@ -156,7 +260,7 @@ jQuery(function($) {
156
260
  'tagged[]': $.makeArray($(this).find('input[name="tagged[]"]').map(function(i, el) { return $(el).attr('checked') ? $(el).val() : null }))
157
261
  });
158
262
 
159
- filter_contacts();
263
+ submit_with_query();
160
264
  });
161
265
 
162
266
  $('form#contact_search_form', $(selector_prefix)).live('submit', function(e) {
@@ -166,7 +270,7 @@ jQuery(function($) {
166
270
  'search': $(this).find('input[name=search]').val()
167
271
  });
168
272
 
169
- filter_contacts();
273
+ submit_with_query();
170
274
  });
171
275
 
172
276
  $('input#contact_search_clear', $(selector_prefix)).live('click', function(e) {
@@ -178,10 +282,10 @@ jQuery(function($) {
178
282
 
179
283
  $.query = {};
180
284
 
181
- filter_contacts();
285
+ submit_with_query();
182
286
  });
183
287
 
184
- //$('#menu_option_key_select_form select').change(function(e) {
288
+ //$('#menu_option_key_select_form select').bindSelectChange(function(e) {
185
289
  //$(this).submit();
186
290
  //});
187
291
  });
@@ -68,9 +68,16 @@ class CreateE9CrmStructure < ActiveRecord::Migration
68
68
  t.timestamps
69
69
  end
70
70
 
71
+ create_table :contacts_deals, :force => true, :id => false do |t|
72
+ t.references :contact, :deal
73
+ end
74
+
71
75
  create_table :deals, :force => true do |t|
72
76
  t.string :type
73
- t.references :offer, :campaign, :tracking_cookie
77
+ t.string :name
78
+ t.string :category
79
+ t.text :info
80
+ t.references :offer, :campaign, :tracking_cookie, :contact
74
81
  t.timestamp :created_at, :updated_at, :converted_at, :closed_at
75
82
  t.string :status, :limit => 32
76
83
  t.integer :value, :default => 0
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.6
5
+ version: 0.1.7
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-19 00:00:00 -04:00
13
+ date: 2011-05-20 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -215,6 +215,7 @@ files:
215
215
  - app/views/e9_crm/contacts/_form_inner.html.haml
216
216
  - app/views/e9_crm/contacts/_header.html.haml
217
217
  - app/views/e9_crm/contacts/_sidebar.html.haml
218
+ - app/views/e9_crm/contacts/_table.html.haml
218
219
  - app/views/e9_crm/contacts/_tag_table.html.haml
219
220
  - app/views/e9_crm/contacts/_who.html.haml
220
221
  - app/views/e9_crm/contacts/index.html.haml
@@ -233,9 +234,11 @@ files:
233
234
  - app/views/e9_crm/dated_costs/new.html.haml
234
235
  - app/views/e9_crm/dated_costs/show.html.haml
235
236
  - app/views/e9_crm/dated_costs/update.js.erb
237
+ - app/views/e9_crm/deals/_footer.html.haml
236
238
  - app/views/e9_crm/deals/_form_inner.html.haml
237
239
  - app/views/e9_crm/deals/_header.html.haml
238
240
  - app/views/e9_crm/deals/_reports_table.html.haml
241
+ - app/views/e9_crm/deals/_table.html.haml
239
242
  - app/views/e9_crm/deals/leads.html.haml
240
243
  - app/views/e9_crm/deals/reports.html.haml
241
244
  - app/views/e9_crm/deals/reports.js.erb