fat_free_crm 0.17.3 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fat_free_crm might be problematic. Click here for more details.

Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +11 -0
  3. data/.rubocop.yml +1 -1
  4. data/.rubocop_todo.yml +30 -8
  5. data/.travis.yml +14 -9
  6. data/CHANGELOG.md +43 -7
  7. data/CONTRIBUTORS.md +95 -53
  8. data/Gemfile +11 -7
  9. data/Gemfile.lock +83 -83
  10. data/README.md +7 -4
  11. data/app/assets/javascripts/crm.js.coffee +3 -3
  12. data/app/assets/javascripts/crm_select2.js.coffee +15 -14
  13. data/app/controllers/admin/field_groups_controller.rb +8 -1
  14. data/app/controllers/admin/fields_controller.rb +4 -4
  15. data/app/controllers/admin/groups_controller.rb +1 -1
  16. data/app/controllers/admin/tags_controller.rb +1 -1
  17. data/app/controllers/application_controller.rb +11 -0
  18. data/app/controllers/authentications_controller.rb +1 -1
  19. data/app/controllers/comments_controller.rb +15 -7
  20. data/app/controllers/entities/campaigns_controller.rb +7 -2
  21. data/app/controllers/entities/leads_controller.rb +9 -2
  22. data/app/controllers/entities/opportunities_controller.rb +13 -2
  23. data/app/controllers/entities_controller.rb +10 -5
  24. data/app/controllers/lists_controller.rb +5 -1
  25. data/app/controllers/tasks_controller.rb +15 -1
  26. data/app/helpers/accounts_helper.rb +1 -1
  27. data/app/helpers/application_helper.rb +2 -2
  28. data/app/helpers/leads_helper.rb +1 -1
  29. data/app/helpers/opportunities_helper.rb +56 -3
  30. data/app/helpers/tags_helper.rb +1 -1
  31. data/app/models/entities/lead.rb +0 -7
  32. data/app/models/entities/opportunity.rb +3 -2
  33. data/app/models/observers/opportunity_observer.rb +4 -4
  34. data/app/models/users/ability.rb +3 -4
  35. data/app/views/campaigns/_metrics.html.haml +3 -3
  36. data/app/views/home/_opportunity.html.haml +4 -19
  37. data/app/views/opportunities/_index_long.html.haml +1 -24
  38. data/app/views/opportunities/_sidebar_show.html.haml +3 -3
  39. data/app/views/opportunities/_top_section.html.haml +1 -1
  40. data/db/schema.rb +0 -3
  41. data/fat_free_crm.gemspec +1 -1
  42. data/lib/fat_free_crm/core_ext/string.rb +1 -1
  43. data/lib/fat_free_crm/engine.rb +2 -2
  44. data/lib/fat_free_crm/fields.rb +1 -1
  45. data/lib/fat_free_crm/permissions.rb +0 -14
  46. data/lib/fat_free_crm/version.rb +2 -2
  47. data/lib/tasks/ffcrm/setup.rake +4 -4
  48. data/spec/controllers/admin/users_controller_spec.rb +27 -27
  49. data/spec/controllers/authentications_controller_spec.rb +7 -7
  50. data/spec/controllers/comments_controller_spec.rb +13 -13
  51. data/spec/controllers/emails_controller_spec.rb +2 -2
  52. data/spec/controllers/entities/accounts_controller_spec.rb +56 -56
  53. data/spec/controllers/entities/campaigns_controller_spec.rb +66 -66
  54. data/spec/controllers/entities/contacts_controller_spec.rb +67 -67
  55. data/spec/controllers/entities/leads_controller_spec.rb +125 -125
  56. data/spec/controllers/entities/opportunities_controller_spec.rb +100 -100
  57. data/spec/controllers/home_controller_spec.rb +26 -26
  58. data/spec/controllers/passwords_controller_spec.rb +1 -1
  59. data/spec/controllers/tasks_controller_spec.rb +37 -37
  60. data/spec/controllers/users_controller_spec.rb +18 -18
  61. data/spec/factories/account_factories.rb +8 -8
  62. data/spec/factories/campaign_factories.rb +5 -5
  63. data/spec/factories/contact_factories.rb +10 -10
  64. data/spec/factories/field_factories.rb +7 -7
  65. data/spec/factories/lead_factories.rb +8 -8
  66. data/spec/factories/list_factories.rb +1 -1
  67. data/spec/factories/opportunity_factories.rb +6 -6
  68. data/spec/factories/sequences.rb +1 -1
  69. data/spec/factories/setting_factories.rb +3 -3
  70. data/spec/factories/shared_factories.rb +14 -14
  71. data/spec/factories/subscription_factories.rb +1 -1
  72. data/spec/factories/tag_factories.rb +1 -1
  73. data/spec/factories/task_factories.rb +4 -4
  74. data/spec/factories/user_factories.rb +13 -13
  75. data/spec/features/accounts_spec.rb +17 -4
  76. data/spec/features/admin/groups_spec.rb +1 -1
  77. data/spec/features/admin/users_spec.rb +1 -1
  78. data/spec/features/campaigns_spec.rb +4 -4
  79. data/spec/features/contacts_spec.rb +10 -4
  80. data/spec/features/dashboard_spec.rb +7 -7
  81. data/spec/features/leads_spec.rb +4 -4
  82. data/spec/features/opportunities_overview_spec.rb +15 -15
  83. data/spec/features/opportunities_spec.rb +34 -8
  84. data/spec/features/support/autocomlete_helper.rb +17 -0
  85. data/spec/features/support/browser.rb +3 -8
  86. data/spec/features/support/helpers.rb +1 -1
  87. data/spec/features/tasks_spec.rb +4 -4
  88. data/spec/helpers/admin/field_groups_helper_spec.rb +1 -1
  89. data/spec/helpers/application_helper_spec.rb +1 -1
  90. data/spec/helpers/tasks_helper_spec.rb +1 -1
  91. data/spec/helpers/users_helper_spec.rb +3 -3
  92. data/spec/lib/comment_extensions_spec.rb +1 -1
  93. data/spec/lib/mail_processor/base_spec.rb +3 -3
  94. data/spec/lib/mail_processor/comment_replies_spec.rb +3 -3
  95. data/spec/lib/mail_processor/dropbox_spec.rb +16 -16
  96. data/spec/lib/permissions_spec.rb +7 -25
  97. data/spec/mailers/user_mailer_spec.rb +7 -7
  98. data/spec/models/entities/account_spec.rb +31 -32
  99. data/spec/models/entities/campaign_spec.rb +18 -25
  100. data/spec/models/entities/contact_spec.rb +18 -21
  101. data/spec/models/entities/lead_spec.rb +9 -11
  102. data/spec/models/entities/opportunity_spec.rb +45 -45
  103. data/spec/models/fields/custom_field_spec.rb +17 -17
  104. data/spec/models/list_spec.rb +2 -2
  105. data/spec/models/observers/entity_observer_spec.rb +6 -6
  106. data/spec/models/polymorphic/address_spec.rb +1 -1
  107. data/spec/models/polymorphic/avatar_spec.rb +5 -5
  108. data/spec/models/polymorphic/comment_spec.rb +5 -5
  109. data/spec/models/polymorphic/task_spec.rb +65 -58
  110. data/spec/models/polymorphic/version_spec.rb +26 -26
  111. data/spec/models/setting_spec.rb +2 -2
  112. data/spec/models/users/preference_spec.rb +6 -6
  113. data/spec/models/users/user_spec.rb +26 -26
  114. data/spec/shared/models.rb +22 -22
  115. data/spec/spec_helper.rb +2 -2
  116. data/spec/support/auth_macros.rb +1 -1
  117. data/spec/support/macros.rb +3 -3
  118. data/spec/views/accounts/_edit.haml_spec.rb +1 -1
  119. data/spec/views/accounts/create.js.haml_spec.rb +2 -2
  120. data/spec/views/accounts/destroy.js.haml_spec.rb +1 -1
  121. data/spec/views/accounts/edit.js.haml_spec.rb +2 -2
  122. data/spec/views/accounts/index.haml_spec.rb +2 -2
  123. data/spec/views/accounts/index.js.haml_spec.rb +1 -1
  124. data/spec/views/accounts/show.haml_spec.rb +4 -4
  125. data/spec/views/accounts/update.js.haml_spec.rb +1 -1
  126. data/spec/views/admin/field_groups/create.js.haml_spec.rb +1 -1
  127. data/spec/views/admin/field_groups/destroy.js.haml_spec.rb +1 -1
  128. data/spec/views/admin/field_groups/edit.js.haml_spec.rb +1 -1
  129. data/spec/views/admin/field_groups/new.js.haml_spec.rb +1 -1
  130. data/spec/views/admin/field_groups/update.js.haml_spec.rb +1 -1
  131. data/spec/views/admin/users/create.js.haml_spec.rb +2 -2
  132. data/spec/views/admin/users/destroy.js.haml_spec.rb +2 -2
  133. data/spec/views/admin/users/edit.js.haml_spec.rb +2 -2
  134. data/spec/views/admin/users/index.haml_spec.rb +1 -1
  135. data/spec/views/admin/users/index.js.haml_spec.rb +2 -2
  136. data/spec/views/admin/users/reactivate.js.haml_spec.rb +1 -1
  137. data/spec/views/admin/users/suspend.js.haml_spec.rb +1 -1
  138. data/spec/views/admin/users/update.js.haml_spec.rb +1 -1
  139. data/spec/views/application/auto_complete.haml_spec.rb +3 -3
  140. data/spec/views/campaigns/_edit.haml_spec.rb +1 -1
  141. data/spec/views/campaigns/create.js.haml_spec.rb +3 -3
  142. data/spec/views/campaigns/destroy.js.haml_spec.rb +1 -1
  143. data/spec/views/campaigns/edit.js.haml_spec.rb +2 -2
  144. data/spec/views/campaigns/index.haml_spec.rb +1 -1
  145. data/spec/views/campaigns/index.js.haml_spec.rb +1 -1
  146. data/spec/views/campaigns/show.haml_spec.rb +4 -4
  147. data/spec/views/campaigns/update.js.haml_spec.rb +1 -1
  148. data/spec/views/contacts/_edit.haml_spec.rb +7 -7
  149. data/spec/views/contacts/_new.haml_spec.rb +1 -1
  150. data/spec/views/contacts/create.js.haml_spec.rb +4 -4
  151. data/spec/views/contacts/destroy.js.haml_spec.rb +1 -1
  152. data/spec/views/contacts/edit.js.haml_spec.rb +3 -3
  153. data/spec/views/contacts/index.haml_spec.rb +1 -1
  154. data/spec/views/contacts/index.js.html_spec.rb +1 -1
  155. data/spec/views/contacts/new.js.haml_spec.rb +1 -1
  156. data/spec/views/contacts/show.haml_spec.rb +3 -3
  157. data/spec/views/contacts/update.js.haml_spec.rb +2 -2
  158. data/spec/views/home/index.haml_spec.rb +1 -1
  159. data/spec/views/home/index.js.haml_spec.rb +1 -1
  160. data/spec/views/home/options.js.haml_spec.rb +2 -2
  161. data/spec/views/leads/_convert.haml_spec.rb +3 -3
  162. data/spec/views/leads/_edit.haml_spec.rb +2 -2
  163. data/spec/views/leads/_new.haml_spec.rb +2 -2
  164. data/spec/views/leads/_sidebar_show.haml_spec.rb +5 -5
  165. data/spec/views/leads/convert.js.haml_spec.rb +4 -4
  166. data/spec/views/leads/create.js.haml_spec.rb +5 -5
  167. data/spec/views/leads/destroy.js.haml_spec.rb +2 -2
  168. data/spec/views/leads/edit.js.haml_spec.rb +4 -4
  169. data/spec/views/leads/index.haml_spec.rb +1 -1
  170. data/spec/views/leads/index.js.haml_spec.rb +1 -1
  171. data/spec/views/leads/new.js.haml_spec.rb +1 -1
  172. data/spec/views/leads/promote.js.haml_spec.rb +7 -7
  173. data/spec/views/leads/reject.js.haml_spec.rb +2 -2
  174. data/spec/views/leads/show.haml_spec.rb +2 -2
  175. data/spec/views/leads/update.js.haml_spec.rb +4 -4
  176. data/spec/views/opportunities/_edit.haml_spec.rb +7 -7
  177. data/spec/views/opportunities/_new.haml_spec.rb +2 -2
  178. data/spec/views/opportunities/create.js.haml_spec.rb +6 -6
  179. data/spec/views/opportunities/destroy.js.haml_spec.rb +3 -3
  180. data/spec/views/opportunities/edit.js.haml_spec.rb +3 -3
  181. data/spec/views/opportunities/index.haml_spec.rb +1 -1
  182. data/spec/views/opportunities/index.js.haml_spec.rb +1 -1
  183. data/spec/views/opportunities/new.js.haml_spec.rb +1 -1
  184. data/spec/views/opportunities/show.haml_spec.rb +3 -3
  185. data/spec/views/opportunities/update.js.haml_spec.rb +4 -4
  186. data/spec/views/tasks/_edit.haml_spec.rb +1 -1
  187. data/spec/views/tasks/complete.js.haml_spec.rb +4 -4
  188. data/spec/views/tasks/create.js.haml_spec.rb +6 -6
  189. data/spec/views/tasks/destroy.js.haml_spec.rb +2 -2
  190. data/spec/views/tasks/index.haml_spec.rb +4 -4
  191. data/spec/views/tasks/new.js.haml_spec.rb +1 -1
  192. data/spec/views/tasks/uncomplete.js.haml_spec.rb +2 -2
  193. data/spec/views/tasks/update.js.haml_spec.rb +18 -18
  194. data/spec/views/users/upload_avatar.js.haml_spec.rb +2 -2
  195. metadata +5 -3
@@ -12,7 +12,7 @@ class OpportunityObserver < ActiveRecord::Observer
12
12
 
13
13
  def after_create(item)
14
14
  if item.campaign && item.stage == "won"
15
- update_campaign_revenue(item.campaign, (item.amount || 0) - (item.discount || 0))
15
+ update_campaign_revenue(item.campaign, item.amount.to_f - item.discount.to_f)
16
16
  end
17
17
  end
18
18
 
@@ -24,11 +24,11 @@ class OpportunityObserver < ActiveRecord::Observer
24
24
  original = @@opportunities.delete(item.id)
25
25
  if original
26
26
  if original.stage != "won" && item.stage == "won" # :other to :won -- add to total campaign revenue.
27
- update_campaign_revenue(item.campaign, (item.amount || 0) - (item.discount || 0))
27
+ update_campaign_revenue(item.campaign, item.amount.to_f - item.discount.to_f)
28
28
  item.update_attribute(:probability, 100) # Set probability to 100% if won
29
29
  return log_activity(item, :won)
30
30
  elsif original.stage == "won" && item.stage != "won" # :won to :other -- substract from total campaign revenue.
31
- update_campaign_revenue(original.campaign, -((original.amount || 0) - (original.discount || 0)))
31
+ update_campaign_revenue(original.campaign, -(original.amount.to_f - original.discount.to_f))
32
32
  elsif original.stage != "lost" && item.stage == "lost"
33
33
  item.update_attribute(:probability, 0) # Set probability to 0% if lost
34
34
  end
@@ -42,7 +42,7 @@ class OpportunityObserver < ActiveRecord::Observer
42
42
  end
43
43
 
44
44
  def update_campaign_revenue(campaign, revenue)
45
- campaign&.update_attribute(:revenue, (campaign.revenue || 0) + revenue)
45
+ campaign&.update_attribute(:revenue, campaign.revenue.to_f + revenue)
46
46
  end
47
47
 
48
48
  ActiveSupport.run_load_hooks(:fat_free_crm_opportunity_observer, self)
@@ -47,10 +47,9 @@ class Ability
47
47
  scope = scope.or(t[:group_id].eq_any(group_ids))
48
48
  end
49
49
 
50
- entities.each do |klass|
51
- if (asset_ids = Permission.where(scope.and(t[:asset_type].eq(klass.name))).pluck(:asset_id)).any?
52
- can :manage, klass, id: asset_ids
53
- end
50
+ permissions = Permission.select(:asset_type, :asset_id).where(scope).where(asset_type: entities.map { |k| k.name.to_s })
51
+ permissions.each do |p|
52
+ can :manage, p.asset_type.constantize, id: p.asset_id
54
53
  end
55
54
  end
56
55
 
@@ -9,8 +9,8 @@
9
9
  %dt
10
10
  - unless objectives.empty?
11
11
  %b #{t :actual}:
12
- = t(:revenue_number, number_to_currency(campaign.revenue || 0, precision: 0)) + " | "
13
- = t('pluralize.lead', campaign.leads_count || 0) + " | "
14
- = t('pluralize.opportunity', campaign.opportunities_count || 0)
12
+ = t(:revenue_number, number_to_currency(campaign.revenue.to_f, precision: 0)) + " | "
13
+ = t('pluralize.lead', campaign.leads_count.to_i) + " | "
14
+ = t('pluralize.opportunity', campaign.opportunities_count.to_i)
15
15
  - if campaign.opportunities_count? && campaign.leads_count? && campaign.leads_count != 0
16
16
  = " | " + t(:conversion_number, number_to_percentage(campaign.opportunities_count * 100 / campaign.leads_count, precision: 1))
@@ -17,25 +17,10 @@
17
17
  = t(:added_ago, value: timeago(opportunity.created_at)).html_safe
18
18
  - unless current_user.preference[:opportunities_index_view] == "opportunities_index_brief"
19
19
  %dt
20
- %b= number_to_currency(opportunity.weighted_amount, precision: 0) + " | "
21
- - won_or_lost = %w(won lost).include?(opportunity.stage)
22
- - unless won_or_lost
23
- = t(:probability_number, (opportunity.probability || 0).to_s + '%') + " | "
24
- - if opportunity.closes_on
25
- - if won_or_lost
26
- - if opportunity.closes_on >= Date.today
27
- = t(:closing_date, l(opportunity.closes_on, format: :mmddyy))
28
- - else
29
- = t(:closed_ago_on, time_ago: distance_of_time_in_words(opportunity.closes_on, Date.today), date: l(opportunity.closes_on, format: :mmddyy))
30
- - elsif opportunity.closes_on > Date.today
31
- = t(:expected_to_close, time: distance_of_time_in_words(Date.today, opportunity.closes_on), date: l(opportunity.closes_on, format: :mmddyy))
32
- - elsif opportunity.closes_on == Date.today
33
- %span.warn= t(:closes_today)
34
- - else
35
- %span.warn= t(:past_due, distance_of_time_in_words(opportunity.closes_on, Date.today))
36
- - else
37
- = t(:no_closing_date)
20
+ = opportunity_revenue_message(opportunity)
21
+
38
22
  - if opportunity.tags.present?
39
23
  %dt
40
24
  .tags= tags_for_dashboard(opportunity)
41
- = hook(:opportunity_bottom, self, opportunity: opportunity)
25
+
26
+ = hook(:opportunity_bottom, self, opportunity: opportunity)
@@ -27,30 +27,7 @@
27
27
  = t(:added_ago, value: timeago(opportunity.created_at)).html_safe
28
28
 
29
29
  %dt
30
- %b= number_to_currency(opportunity.weighted_amount, precision: 0) + " | "
31
- - won_or_lost = %w(won lost).include?(opportunity.stage)
32
- - unless won_or_lost
33
- = number_to_currency(opportunity.amount || 0, precision: 0)
34
- - if opportunity.discount
35
- = t(:discount_number, number_to_currency(opportunity.discount, precision: 0))
36
- - else
37
- = t(:no_discount)
38
- = t(:probability_number, (opportunity.probability || 0).to_s + '%') + " | "
39
-
40
- - if opportunity.closes_on
41
- - if won_or_lost
42
- - if opportunity.closes_on >= Date.today
43
- = t(:closing_date, l(opportunity.closes_on, format: :mmddyy))
44
- - else
45
- = t(:closed_ago_on, time_ago: distance_of_time_in_words(opportunity.closes_on, Date.today), date: l(opportunity.closes_on, format: :mmddyy))
46
- - elsif opportunity.closes_on > Date.today
47
- = t(:expected_to_close, time: distance_of_time_in_words(Date.today, opportunity.closes_on), date: l(opportunity.closes_on, format: :mmddyy))
48
- - elsif opportunity.closes_on == Date.today
49
- %span.warn= t(:closes_today)
50
- - else
51
- %span.warn= t(:past_due, distance_of_time_in_words(opportunity.closes_on, Date.today))
52
- - else
53
- = t(:no_closing_date)
30
+ = opportunity_revenue_message(opportunity, true)
54
31
 
55
32
  - if opportunity.tags.present?
56
33
  %dt
@@ -19,16 +19,16 @@
19
19
  %dt= @opportunity.probability ? @opportunity.probability.to_s + "%" : t(:n_a)
20
20
  %tt #{t :probability}:
21
21
  %li
22
- %dt= @opportunity.amount ? number_to_currency(@opportunity.amount || 0, precision: 0) : t(:n_a)
22
+ %dt= @opportunity.amount ? number_to_currency(@opportunity.amount.to_f, precision: 0) : t(:n_a)
23
23
  %tt #{t :amount}:
24
24
  %li
25
- %dt= @opportunity.discount ? number_to_currency(@opportunity.discount || 0, precision: 0) : t(:n_a)
25
+ %dt= @opportunity.discount ? number_to_currency(@opportunity.discount.to_f, precision: 0) : t(:n_a)
26
26
  - if @opportunity.amount && @opportunity.discount
27
27
  %tt== Discount (#{number_to_percentage(@opportunity.discount / @opportunity.amount * 100, precision: 1)}):
28
28
  - else
29
29
  %tt #{t :discount}:
30
30
  %li
31
- %dt= @opportunity.amount ? number_to_currency(@opportunity.weighted_amount || 0, precision: 0) : t(:n_a)
31
+ %dt= @opportunity.amount ? number_to_currency(@opportunity.weighted_amount.to_f, precision: 0) : t(:n_a)
32
32
  %tt #{t :weighted_amount}:
33
33
  %li
34
34
  %dt= @opportunity.assigned_to ? truncate(@opportunity.assignee.full_name, length: 16) : nil
@@ -37,7 +37,7 @@
37
37
  %td
38
38
  != account_select_or_create(a) do |options|
39
39
  -# Add [-- None --] account choice when editing existing opportunity that has an account.
40
- - options[:selected] = @account.id || 0
40
+ - options[:selected] = @account.id.to_i
41
41
 
42
42
  %td= spacer
43
43
  %td
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # This file is auto-generated from the current state of the database. Instead
4
2
  # of editing this file, please use the migrations feature of Active Record to
5
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -54,7 +52,6 @@ ActiveRecord::Schema.define(version: 20180103223438) do
54
52
  t.text "subscribed_users"
55
53
  t.integer "contacts_count", default: 0
56
54
  t.integer "opportunities_count", default: 0
57
- t.integer "pipeline_opportunities_count", default: 0
58
55
  t.index ["assigned_to"], name: "index_accounts_on_assigned_to"
59
56
  t.index ["user_id", "name", "deleted_at"], name: "index_accounts_on_user_id_and_name_and_deleted_at", unique: true
60
57
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
18
18
  gem.email = ['mike@fatfreecrm.com', 'nathan@fatfreecrm.com', 'warp@fatfreecrm.com', 'steveyken@gmail.com', 'daniel.oconnor@gmail.com']
19
19
  gem.files = files
20
20
  gem.version = FatFreeCRM::VERSION::STRING
21
- gem.required_ruby_version = '>= 2.3.0'
21
+ gem.required_ruby_version = '>= 2.4.0'
22
22
  gem.license = 'MIT'
23
23
 
24
24
  gem.add_dependency 'rails', '~> 5.1.0'
@@ -21,7 +21,7 @@ class String
21
21
  end
22
22
 
23
23
  def to_url
24
- match(/^https?:\/\//) ? self : "http://#{self}"
24
+ match?(/^https?:\/\//) ? self : "http://#{self}"
25
25
  end
26
26
 
27
27
  def true?
@@ -13,8 +13,8 @@ module FatFreeCRM
13
13
  config.active_record.observers = %i[lead_observer opportunity_observer
14
14
  task_observer entity_observer]
15
15
 
16
- initializer "model_core.factories", after: "factory_girl.set_factory_paths" do
17
- FactoryGirl.definition_file_paths << File.expand_path('../../../spec/factories', __FILE__) if defined?(FactoryGirl)
16
+ initializer "model_core.factories", after: "factory_bot.set_factory_paths" do
17
+ FactoryBot.definition_file_paths << File.expand_path('../../../spec/factories', __FILE__) if defined?(FactoryBot)
18
18
  end
19
19
 
20
20
  initializer :append_migrations do |app|
@@ -75,7 +75,7 @@ module FatFreeCRM
75
75
  end
76
76
 
77
77
  def method_missing(method_id, *args, &block)
78
- if method_id.to_s =~ /\Acf_.*[^=]\Z/
78
+ if method_id.to_s.match?(/\Acf_.*[^=]\Z/)
79
79
  # Refresh columns and try again.
80
80
  self.class.reset_column_information
81
81
  # If new record, create new object from class, else reload class
@@ -76,20 +76,6 @@ module FatFreeCRM
76
76
  permissions_to_remove.each { |p| permissions.delete(p); p.destroy }
77
77
  end
78
78
 
79
- # Save the model along with its permissions if any.
80
- #--------------------------------------------------------------------------
81
- def save_with_permissions(_users = nil)
82
- ActiveSupport::Deprecation.warn "save_with_permissions is deprecated and may be removed from future releases, use user_ids and group_ids inside attributes instead."
83
- save
84
- end
85
-
86
- # Update the model along with its permissions if any.
87
- #--------------------------------------------------------------------------
88
- def update_with_permissions(attributes, _users = nil)
89
- ActiveSupport::Deprecation.warn "update_with_permissions is deprecated and may be removed from future releases, use user_ids and group_ids inside attributes instead."
90
- update_attributes(attributes)
91
- end
92
-
93
79
  # Save the model copying other model's permissions.
94
80
  #--------------------------------------------------------------------------
95
81
  def save_with_model_permissions(model)
@@ -8,8 +8,8 @@
8
8
  module FatFreeCRM
9
9
  module VERSION #:nodoc:
10
10
  MAJOR = 0
11
- MINOR = 17
12
- TINY = 3
11
+ MINOR = 18
12
+ TINY = 0
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -18,7 +18,7 @@ namespace :ffcrm do
18
18
  end
19
19
 
20
20
  # Don't continue unless user typed y(es)
21
- if proceed =~ /y(?:es)*/i
21
+ if proceed.match?(/y(?:es)*/i)
22
22
  Rake::Task["db:migrate"].invoke
23
23
  Rake::Task["ffcrm:setup:admin"].invoke
24
24
  else
@@ -44,7 +44,7 @@ namespace :ffcrm do
44
44
 
45
45
  password ||= "manager"
46
46
  print "Password [#{password}]: "
47
- echo = ->(toggle) { return if RUBY_PLATFORM =~ /mswin/; system(toggle ? "stty echo && echo" : "stty -echo") }
47
+ echo = ->(toggle) { return if RUBY_PLATFORM.match?(/mswin/); system(toggle ? "stty echo && echo" : "stty -echo") }
48
48
  begin
49
49
  echo.call(false)
50
50
  reply = STDIN.gets.strip
@@ -68,8 +68,8 @@ namespace :ffcrm do
68
68
  reply = STDIN.gets.strip
69
69
  break unless reply.blank?
70
70
  end
71
- break if reply =~ /y(?:es)*/i
72
- redo if reply =~ /no*/i
71
+ break if reply.match?(/y(?:es)*/i)
72
+ redo if reply.match?(/no*/i)
73
73
  puts "No admin user was created."
74
74
  exit
75
75
  end
@@ -18,7 +18,7 @@ describe Admin::UsersController do
18
18
  #----------------------------------------------------------------------------
19
19
  describe "GET index" do
20
20
  it "assigns all users as @users and renders [index] template" do
21
- @users = [current_user, FactoryGirl.create(:user)]
21
+ @users = [current_user, create(:user)]
22
22
 
23
23
  get :index
24
24
  expect(assigns[:users].first).to eq(@users.last) # get_users() sorts by id DESC
@@ -27,8 +27,8 @@ describe Admin::UsersController do
27
27
  end
28
28
 
29
29
  it "performs lookup using query string" do
30
- @amy = FactoryGirl.create(:user, username: "amy_anderson")
31
- @bob = FactoryGirl.create(:user, username: "bob_builder")
30
+ @amy = create(:user, username: "amy_anderson")
31
+ @bob = create(:user, username: "bob_builder")
32
32
 
33
33
  get :index, params: { query: "amy_anderson" }
34
34
  expect(assigns[:users]).to eq([@amy])
@@ -42,7 +42,7 @@ describe Admin::UsersController do
42
42
  #----------------------------------------------------------------------------
43
43
  describe "GET show" do
44
44
  it "assigns the requested user as @user and renders [show] template" do
45
- @user = FactoryGirl.create(:user)
45
+ @user = create(:user)
46
46
 
47
47
  get :show, params: { id: @user.id }
48
48
  expect(assigns[:user]).to eq(@user)
@@ -65,7 +65,7 @@ describe Admin::UsersController do
65
65
  #----------------------------------------------------------------------------
66
66
  describe "GET edit" do
67
67
  it "assigns the requested user as @user and renders [edit] template" do
68
- @user = FactoryGirl.create(:user)
68
+ @user = create(:user)
69
69
 
70
70
  get :edit, params: { id: @user.id }, xhr: true
71
71
  expect(assigns[:user]).to eq(@user)
@@ -74,15 +74,15 @@ describe Admin::UsersController do
74
74
  end
75
75
 
76
76
  it "assigns the previous user as @previous when necessary" do
77
- @user = FactoryGirl.create(:user)
78
- @previous = FactoryGirl.create(:user)
77
+ @user = create(:user)
78
+ @previous = create(:user)
79
79
 
80
80
  get :edit, params: { id: @user.id, previous: @previous.id }, xhr: true
81
81
  expect(assigns[:previous]).to eq(@previous)
82
82
  end
83
83
 
84
84
  it "reloads current page with the flash message if user got deleted" do
85
- @user = FactoryGirl.create(:user)
85
+ @user = create(:user)
86
86
  @user.destroy
87
87
 
88
88
  get :edit, params: { id: @user.id }, xhr: true
@@ -91,8 +91,8 @@ describe Admin::UsersController do
91
91
  end
92
92
 
93
93
  it "notifies the view if previous user got deleted" do
94
- @user = FactoryGirl.create(:user)
95
- @previous = FactoryGirl.create(:user)
94
+ @user = create(:user)
95
+ @previous = create(:user)
96
96
  @previous.destroy
97
97
 
98
98
  get :edit, params: { id: @user.id, previous: @previous.id }, xhr: true
@@ -114,7 +114,7 @@ describe Admin::UsersController do
114
114
  end
115
115
 
116
116
  it "assigns a newly created user as @user and renders [create] template" do
117
- @user = FactoryGirl.build(:user, username: @username, email: @email)
117
+ @user = build(:user, username: @username, email: @email)
118
118
  allow(User).to receive(:new).and_return(@user)
119
119
 
120
120
  post :create, params: { user: { username: @username, email: @email, password: @password, password_confirmation: @password } }, xhr: true
@@ -137,7 +137,7 @@ describe Admin::UsersController do
137
137
 
138
138
  describe "with invalid params" do
139
139
  it "assigns a newly created but unsaved user as @user and re-renders [create] template" do
140
- @user = FactoryGirl.build(:user, username: "", email: "")
140
+ @user = build(:user, username: "", email: "")
141
141
  allow(User).to receive(:new).and_return(@user)
142
142
 
143
143
  post :create, params: { user: {} }, xhr: true
@@ -153,7 +153,7 @@ describe Admin::UsersController do
153
153
  describe "PUT update" do
154
154
  describe "with valid params" do
155
155
  it "updates the requested user, assigns it to @user, and renders [update] template" do
156
- @user = FactoryGirl.create(:user, username: "flip", email: "flip@example.com")
156
+ @user = create(:user, username: "flip", email: "flip@example.com")
157
157
 
158
158
  put :update, params: { id: @user.id, user: { username: "flop", email: "flop@example.com" } }, xhr: true
159
159
  expect(assigns[:user]).to eq(@user.reload)
@@ -162,7 +162,7 @@ describe Admin::UsersController do
162
162
  end
163
163
 
164
164
  it "reloads current page is the user got deleted" do
165
- @user = FactoryGirl.create(:user)
165
+ @user = create(:user)
166
166
  @user.destroy
167
167
 
168
168
  put :update, params: { id: @user.id, user: { username: "flop", email: "flop@example.com" } }, xhr: true
@@ -171,7 +171,7 @@ describe Admin::UsersController do
171
171
  end
172
172
 
173
173
  it "assigns admin rights when requested so" do
174
- @user = FactoryGirl.create(:user, admin: false)
174
+ @user = create(:user, admin: false)
175
175
  put :update, params: { id: @user.id, user: { admin: "1", username: @user.username, email: @user.email } }, xhr: true
176
176
  expect(assigns[:user]).to eq(@user.reload)
177
177
  expect(assigns[:user].admin).to eq(true)
@@ -179,7 +179,7 @@ describe Admin::UsersController do
179
179
  end
180
180
 
181
181
  it "revokes admin rights when requested so" do
182
- @user = FactoryGirl.create(:user, admin: true)
182
+ @user = create(:user, admin: true)
183
183
  put :update, params: { id: @user.id, user: { admin: "0", username: @user.username, email: @user.email } }, xhr: true
184
184
  expect(assigns[:user]).to eq(@user.reload)
185
185
  expect(assigns[:user].admin).to eq(false)
@@ -189,7 +189,7 @@ describe Admin::UsersController do
189
189
 
190
190
  describe "with invalid params" do
191
191
  it "doesn't update the requested user, but assigns it to @user and renders [update] template" do
192
- @user = FactoryGirl.create(:user, username: "flip", email: "flip@example.com")
192
+ @user = create(:user, username: "flip", email: "flip@example.com")
193
193
 
194
194
  put :update, params: { id: @user.id, user: {} }, xhr: true
195
195
  expect(assigns[:user]).to eq(@user.reload)
@@ -203,7 +203,7 @@ describe Admin::UsersController do
203
203
  #----------------------------------------------------------------------------
204
204
  describe "GET confirm" do
205
205
  it "assigns the requested user as @user and renders [confirm] template" do
206
- @user = FactoryGirl.create(:user)
206
+ @user = create(:user)
207
207
 
208
208
  get :confirm, params: { id: @user.id }, xhr: true
209
209
  expect(assigns[:user]).to eq(@user)
@@ -211,7 +211,7 @@ describe Admin::UsersController do
211
211
  end
212
212
 
213
213
  it "reloads current page is the user got deleted" do
214
- @user = FactoryGirl.create(:user)
214
+ @user = create(:user)
215
215
  @user.destroy
216
216
 
217
217
  get :confirm, params: { id: @user.id }, xhr: true
@@ -225,7 +225,7 @@ describe Admin::UsersController do
225
225
  #----------------------------------------------------------------------------
226
226
  describe "DELETE destroy" do
227
227
  it "destroys the requested user and renders [destroy] template" do
228
- @user = FactoryGirl.create(:user)
228
+ @user = create(:user)
229
229
 
230
230
  delete :destroy, params: { id: @user.id }, xhr: true
231
231
  expect { User.find(@user.id) }.to raise_error(ActiveRecord::RecordNotFound)
@@ -233,8 +233,8 @@ describe Admin::UsersController do
233
233
  end
234
234
 
235
235
  it "handles the case when the requested user can't be deleted" do
236
- @user = FactoryGirl.create(:user)
237
- @account = FactoryGirl.create(:account, user: @user) # Plant artifact to prevent the user from being deleted.
236
+ @user = create(:user)
237
+ @account = create(:account, user: @user) # Plant artifact to prevent the user from being deleted.
238
238
 
239
239
  delete :destroy, params: { id: @user.id }, xhr: true
240
240
  expect(flash[:warning]).not_to eq(nil)
@@ -247,7 +247,7 @@ describe Admin::UsersController do
247
247
  #----------------------------------------------------------------------------
248
248
  describe "POST auto_complete" do
249
249
  before(:each) do
250
- @auto_complete_matches = [FactoryGirl.create(:user, first_name: "Hello")]
250
+ @auto_complete_matches = [create(:user, first_name: "Hello")]
251
251
  end
252
252
 
253
253
  it_should_behave_like("auto complete")
@@ -258,7 +258,7 @@ describe Admin::UsersController do
258
258
  #----------------------------------------------------------------------------
259
259
  describe "PUT suspend" do
260
260
  it "suspends the requested user" do
261
- @user = FactoryGirl.create(:user)
261
+ @user = create(:user)
262
262
 
263
263
  put :suspend, params: { id: @user.id }, xhr: true
264
264
  expect(assigns[:user].suspended?).to eq(true)
@@ -274,7 +274,7 @@ describe Admin::UsersController do
274
274
  end
275
275
 
276
276
  it "reloads current page is the user got deleted" do
277
- @user = FactoryGirl.create(:user)
277
+ @user = create(:user)
278
278
  @user.destroy
279
279
 
280
280
  put :suspend, params: { id: @user.id }, xhr: true
@@ -288,7 +288,7 @@ describe Admin::UsersController do
288
288
  #----------------------------------------------------------------------------
289
289
  describe "PUT reactivate" do
290
290
  it "re-activates the requested user" do
291
- @user = FactoryGirl.create(:user, suspended_at: Time.now.yesterday)
291
+ @user = create(:user, suspended_at: Time.now.yesterday)
292
292
 
293
293
  put :reactivate, params: { id: @user.id }, xhr: true
294
294
  expect(assigns[:user].suspended?).to eq(false)
@@ -296,7 +296,7 @@ describe Admin::UsersController do
296
296
  end
297
297
 
298
298
  it "reloads current page is the user got deleted" do
299
- @user = FactoryGirl.create(:user)
299
+ @user = create(:user)
300
300
  @user.destroy
301
301
 
302
302
  put :reactivate, params: { id: @user.id }, xhr: true