approval_cycle 0.1.0.pre → 0.1.1.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -15
  3. data/app/models/approval_cycle/setup.rb +6 -3
  4. data/app/models/concerns/approval_cycle/approvable.rb +5 -5
  5. data/app/models/concerns/enums/approval_cycle/approval.rb +9 -1
  6. data/db/migrate/20240723091231_create_approval_cycle_setups.rb +3 -3
  7. data/lib/approval_cycle/configuration.rb +16 -1
  8. data/lib/approval_cycle/version.rb +1 -1
  9. data/lib/generators/approval_cycle/install/templates/approval_cycle.rb +13 -1
  10. data/lib/generators/approval_cycle/setup_types_generator.rb +49 -5
  11. data/lib/tasks/approval_cycle_tasks.rake +17 -17
  12. data/spec/dummy/app/models/dummy_request.rb +1 -0
  13. data/spec/dummy/config/initializers/approval_cycle.rb +24 -1
  14. data/spec/dummy/db/migrate/{20250731094005_create_approval_cycle_setups.rb → 20250731123034_create_approval_cycle_setups.rb} +3 -3
  15. data/spec/dummy/db/schema.rb +4 -5
  16. data/spec/dummy/log/development.log +121 -0
  17. data/spec/dummy/log/test.log +55486 -0
  18. data/spec/features/configurable_approval_statuses_demo_spec.rb +76 -0
  19. data/spec/lib/approval_cycle/configuration_spec.rb +81 -0
  20. data/spec/models/approval_cycle/approval_spec.rb +38 -9
  21. data/spec/models/approval_cycle/setup_spec.rb +2 -0
  22. data/spec/services/approval_cycle/setup_updater_spec.rb +5 -3
  23. metadata +19 -18
  24. data/db/migrate/20240723091230_enable_pg_trgm_extention.rb +0 -9
  25. data/spec/dummy/db/migrate/20250731094004_enable_pg_trgm_extention.rb +0 -9
  26. /data/spec/dummy/db/migrate/{20250731094006_create_approval_cycle_approvers.rb → 20250731123035_create_approval_cycle_approvers.rb} +0 -0
  27. /data/spec/dummy/db/migrate/{20250731094007_create_approval_cycle_watchers.rb → 20250731123036_create_approval_cycle_watchers.rb} +0 -0
  28. /data/spec/dummy/db/migrate/{20250731094008_create_approval_cycle_action_takers.rb → 20250731123037_create_approval_cycle_action_takers.rb} +0 -0
  29. /data/spec/dummy/db/migrate/{20250731094009_create_approval_cycle_object_activities.rb → 20250731123038_create_approval_cycle_object_activities.rb} +0 -0
  30. /data/spec/dummy/db/migrate/{20250731094010_create_approval_cycle_approvals.rb → 20250731123039_create_approval_cycle_approvals.rb} +0 -0
  31. /data/spec/dummy/db/migrate/{20250731094101_add_approval_cycle_to_configured_types.rb → 20250731123227_add_approval_cycle_to_configured_types.rb} +0 -0
@@ -0,0 +1,76 @@
1
+ require 'rails_helper'
2
+
3
+ # Demonstration of configurable approval statuses
4
+ RSpec.describe 'Configurable Approval Statuses Demo', type: :model do
5
+ describe 'Configured approval statuses' do
6
+ it 'uses the configured custom statuses for dummy_request' do
7
+ # Since we have custom statuses configured in the dummy app initializer
8
+ expected_statuses = %w[pending approved rejected cancelled on_hold auto_approved skipped_after_rejection skipped_after_withdrawal]
9
+ actual_statuses = ApprovalCycle::Approval.statuses.keys
10
+
11
+ expect(actual_statuses).to match_array(expected_statuses)
12
+ end
13
+ end
14
+
15
+ describe 'Custom approval statuses configuration' do
16
+ it 'allows configuration to be set' do
17
+ # This demonstrates how a user would configure custom statuses for dummy_request
18
+ custom_config = ApprovalCycle::Configuration.new
19
+ custom_config.approval_statuses = {
20
+ pending: 'pending',
21
+ approved: 'approved',
22
+ rejected: 'rejected',
23
+ cancelled: 'cancelled',
24
+ on_hold: 'on_hold'
25
+ }
26
+
27
+ expect(custom_config.approval_statuses.keys).to contain_exactly(
28
+ :pending, :approved, :rejected, :cancelled, :on_hold
29
+ )
30
+ end
31
+
32
+ it 'provides access to custom statuses via configuration for dummy_request' do
33
+ # This shows how the enum accesses the configuration for dummy_request workflow
34
+ ApprovalCycle.configure do |config|
35
+ config.approval_cycle_setup_types = { dummy_request: 0 }
36
+ config.approval_statuses = {
37
+ pending: 'pending',
38
+ approved: 'approved',
39
+ rejected: 'rejected',
40
+ cancelled: 'cancelled',
41
+ on_hold: 'on_hold'
42
+ }
43
+ end
44
+
45
+ # The configuration is available and can be accessed
46
+ expect(ApprovalCycle.configuration.approval_statuses).to include(
47
+ pending: 'pending',
48
+ approved: 'approved',
49
+ rejected: 'rejected',
50
+ cancelled: 'cancelled',
51
+ on_hold: 'on_hold'
52
+ )
53
+ end
54
+ end
55
+
56
+ describe 'Fallback behavior' do
57
+ it 'uses fallback statuses when configuration is nil' do
58
+ # Simulate the enum fallback behavior
59
+ config_statuses = nil
60
+ fallback_statuses = {
61
+ pending: 'pending',
62
+ rejected: 'rejected',
63
+ approved: 'approved',
64
+ skipped: 'skipped',
65
+ auto_approved: 'auto_approved',
66
+ skipped_after_rejection: 'skipped_after_rejection',
67
+ skipped_after_withdrawal: 'skipped_after_withdrawal'
68
+ }
69
+
70
+ # This is what happens in the enum definition
71
+ used_statuses = config_statuses || fallback_statuses
72
+
73
+ expect(used_statuses).to eq(fallback_statuses)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,81 @@
1
+ require 'rails_helper'
2
+
3
+ module ApprovalCycle
4
+ RSpec.describe Configuration do
5
+ let(:config) { Configuration.new }
6
+
7
+ describe '#approval_statuses' do
8
+ it 'has default approval statuses' do
9
+ expect(config.approval_statuses).to eq({
10
+ pending: 'pending',
11
+ rejected: 'rejected',
12
+ approved: 'approved',
13
+ skipped: 'skipped',
14
+ auto_approved: 'auto_approved',
15
+ skipped_after_rejection: 'skipped_after_rejection',
16
+ skipped_after_withdrawal: 'skipped_after_withdrawal'
17
+ })
18
+ end
19
+
20
+ it 'allows custom approval statuses to be set' do
21
+ custom_statuses = {
22
+ pending: 'pending',
23
+ approved: 'approved',
24
+ rejected: 'rejected',
25
+ cancelled: 'cancelled'
26
+ }
27
+
28
+ config.approval_statuses = custom_statuses
29
+ expect(config.approval_statuses).to eq(custom_statuses)
30
+ end
31
+ end
32
+
33
+ describe '#approval_cycle_setup_types' do
34
+ it 'starts with empty setup types' do
35
+ expect(config.approval_cycle_setup_types).to eq({})
36
+ end
37
+
38
+ it 'allows setup types to be set' do
39
+ setup_types = { dummy_request: 0 }
40
+ config.approval_cycle_setup_types = setup_types
41
+ expect(config.approval_cycle_setup_types).to eq(setup_types)
42
+ end
43
+ end
44
+ end
45
+
46
+ RSpec.describe 'ApprovalCycle.configure' do
47
+ around do |example|
48
+ original_config = ApprovalCycle.configuration
49
+ example.run
50
+ ApprovalCycle.configuration = original_config
51
+ end
52
+
53
+ it 'allows configuration of approval statuses' do
54
+ ApprovalCycle.configure do |config|
55
+ config.approval_statuses = {
56
+ pending: 'pending',
57
+ approved: 'approved',
58
+ rejected: 'rejected',
59
+ cancelled: 'cancelled'
60
+ }
61
+ end
62
+
63
+ expect(ApprovalCycle.configuration.approval_statuses).to eq({
64
+ pending: 'pending',
65
+ approved: 'approved',
66
+ rejected: 'rejected',
67
+ cancelled: 'cancelled'
68
+ })
69
+ end
70
+
71
+ it 'allows configuration of setup types' do
72
+ ApprovalCycle.configure do |config|
73
+ config.approval_cycle_setup_types = { dummy_request: 0 }
74
+ end
75
+
76
+ expect(ApprovalCycle.configuration.approval_cycle_setup_types).to eq({
77
+ dummy_request: 0
78
+ })
79
+ end
80
+ end
81
+ end
@@ -10,8 +10,8 @@ module ApprovalCycle
10
10
  let(:fourth_user) { users.fourth }
11
11
  let(:user) { create(:dummy_user) }
12
12
  let(:approver) { create(:approver, user_id: user.id, user_type: 'DummyUser', approval_cycle_setup: setup, order: 10) }
13
- let(:approvers) { [ { user_id: first_user.id, order: 0, user_type: 'DummyUser' }, { user_id: second_user.id, order: 1, user_type: 'DummyUser' }, { user_id: third_user.id, order: 2, user_type: 'DummyUser' } ] }
14
- let(:setup) { create(:setup, level: company, approval_cycle_setup_type: :dummy_request, modifier: user, approval_cycle_approvers_attributes: approvers, approval_cycle_watchers_attributes: [ { user_id: user.id, user_type: 'DummyUser', action: 'both' } ], approval_cycle_action_takers_attributes: [ { user_id: user.id, user_type: 'DummyUser' } ]) }
13
+ let(:approvers) { [{ user_id: first_user.id, order: 0, user_type: 'DummyUser' }, { user_id: second_user.id, order: 1, user_type: 'DummyUser' }, { user_id: third_user.id, order: 2, user_type: 'DummyUser' }] }
14
+ let(:setup) { create(:setup, level: company, approval_cycle_setup_type: :dummy_request, modifier: user, approval_cycle_approvers_attributes: approvers, approval_cycle_watchers_attributes: [{ user_id: user.id, user_type: 'DummyUser', action: 'both' }], approval_cycle_action_takers_attributes: [{ user_id: user.id, user_type: 'DummyUser' }]) }
15
15
  let(:second_setup) { create(:setup, level: company, modifier: user, approval_cycle_setup_type: :dummy_request) }
16
16
  let(:dummy_request) { create(:dummy_request, approval_cycle_setup: setup, approval_cycle_status: :pending, modifier: user) }
17
17
  let(:subject) { create(:approval, approval_cycle_approver: approver, approvable: dummy_request) }
@@ -28,7 +28,36 @@ module ApprovalCycle
28
28
  end
29
29
 
30
30
  describe 'Enums' do
31
- it { should define_enum_for(:status).with_values({ pending: 'pending', rejected: 'rejected', approved: 'approved', skipped: 'skipped', auto_approved: 'auto_approved', skipped_after_rejection: 'skipped_after_rejection', skipped_after_withdrawal: 'skipped_after_withdrawal' }).backed_by_column_of_type(:string).with_prefix(true) }
31
+ it { should define_enum_for(:status).with_values({ pending: 'pending', approved: 'approved', rejected: 'rejected', cancelled: 'cancelled', on_hold: 'on_hold', auto_approved: 'auto_approved', skipped_after_rejection: 'skipped_after_rejection', skipped_after_withdrawal: 'skipped_after_withdrawal' }).backed_by_column_of_type(:string).with_prefix(true) }
32
+
33
+ context 'with custom approval statuses' do
34
+ around do |example|
35
+ original_config = ApprovalCycle.configuration
36
+ ApprovalCycle.configuration = ApprovalCycle::Configuration.new
37
+ ApprovalCycle.configure do |config|
38
+ config.approval_cycle_setup_types = { dummy_request: 0 }
39
+ config.approval_statuses = {
40
+ pending: 'pending',
41
+ approved: 'approved',
42
+ rejected: 'rejected',
43
+ cancelled: 'cancelled'
44
+ }
45
+ end
46
+
47
+ example.run
48
+
49
+ ApprovalCycle.configuration = original_config
50
+ end
51
+
52
+ it 'allows custom statuses to be configured' do
53
+ expect(ApprovalCycle.configuration.approval_statuses).to eq({
54
+ pending: 'pending',
55
+ approved: 'approved',
56
+ rejected: 'rejected',
57
+ cancelled: 'cancelled'
58
+ })
59
+ end
60
+ end
32
61
  end
33
62
 
34
63
  describe '#update_next_approval_received_at' do
@@ -69,7 +98,7 @@ module ApprovalCycle
69
98
  context 'when current approval is first approval' do
70
99
  it 'does not update next approval received_at' do
71
100
  expect(current_approval.count).to eq(1)
72
- expect(current_approval.pluck(:status)).to eq([ 'rejected' ])
101
+ expect(current_approval.pluck(:status)).to eq(['rejected'])
73
102
  end
74
103
  end
75
104
  end
@@ -89,7 +118,7 @@ module ApprovalCycle
89
118
  end
90
119
 
91
120
  it 'creates all other approvals with NIL received_at and status' do
92
- expect(Approval.last(2).pluck(:approval_cycle_approver_id, :received_at, :status)).to match_array(awaiting_approvals.map { |approver| [ approver.id, nil, 'pending' ] })
121
+ expect(Approval.last(2).pluck(:approval_cycle_approver_id, :received_at, :status)).to match_array(awaiting_approvals.map { |approver| [approver.id, nil, 'pending'] })
93
122
  end
94
123
  end
95
124
  end
@@ -100,7 +129,7 @@ module ApprovalCycle
100
129
 
101
130
  context 'when created_by is approver' do
102
131
  context 'when approver is first and only approver' do
103
- let(:approvers) { [ { user_id: user.id, order: 0, user_type: 'DummyUser' } ] }
132
+ let(:approvers) { [{ user_id: user.id, order: 0, user_type: 'DummyUser' }] }
104
133
 
105
134
  it 'approves request' do
106
135
  expect(request_status).to eq('approved')
@@ -109,7 +138,7 @@ module ApprovalCycle
109
138
  end
110
139
 
111
140
  context 'when approver is last approver' do
112
- let(:approvers) { [ { user_id: first_user.id, order: 0, user_type: 'DummyUser' }, { user_id: user.id, order: 1, user_type: 'DummyUser' } ] }
141
+ let(:approvers) { [{ user_id: first_user.id, order: 0, user_type: 'DummyUser' }, { user_id: user.id, order: 1, user_type: 'DummyUser' }] }
113
142
 
114
143
  before { Approval.first.approve! }
115
144
 
@@ -120,7 +149,7 @@ module ApprovalCycle
120
149
  end
121
150
 
122
151
  context 'when approver is not last approver' do
123
- let(:approvers) { [ { user_id: first_user.id, order: 0, user_type: 'DummyUser' }, { user_id: user.id, order: 1, user_type: 'DummyUser' }, { user_id: third_user.id, order: 2, user_type: 'DummyUser' } ] }
152
+ let(:approvers) { [{ user_id: first_user.id, order: 0, user_type: 'DummyUser' }, { user_id: user.id, order: 1, user_type: 'DummyUser' }, { user_id: third_user.id, order: 2, user_type: 'DummyUser' }] }
124
153
 
125
154
  before { Approval.first.approve! }
126
155
 
@@ -133,7 +162,7 @@ module ApprovalCycle
133
162
  end
134
163
 
135
164
  context 'when created_by is not approver' do
136
- let(:approvers) { [ { user_id: first_user.id, order: 0, user_type: 'DummyUser' } ] }
165
+ let(:approvers) { [{ user_id: first_user.id, order: 0, user_type: 'DummyUser' }] }
137
166
 
138
167
  it 'does not auto approve' do
139
168
  expect(request_status).to eq('pending')
@@ -1,3 +1,5 @@
1
+ require 'rails_helper'
2
+
1
3
  module ApprovalCycle
2
4
  RSpec.describe Setup, type: :model do
3
5
  let(:company) { create(:company) }
@@ -1,6 +1,8 @@
1
+ require 'rails_helper'
2
+
1
3
  module ApprovalCycle
2
- RSpec.describe SetupUpdater, type: :service do
3
- describe '#call' do
4
+ RSpec.describe SetupUpdater, type: :service do # rubocop:disable Metrics/BlockLength
5
+ describe '#call' do # rubocop:disable Metrics/BlockLength
4
6
  let(:company) { create(:company) }
5
7
  let(:user) { create(:dummy_user) }
6
8
  let(:setup_attrs) { { approval_cycle_approvers_attributes: [ { user_id: user.id, order: 0, user_type: 'DummyUser' } ], approval_cycle_watchers_attributes: [ { user_id: user.id, action: 'both', user_type: 'DummyUser' } ], approval_cycle_action_takers_attributes: [ { user_id: user.id, user_type: 'DummyUser' } ] } }
@@ -14,7 +16,7 @@ module ApprovalCycle
14
16
 
15
17
  before { dummy_request }
16
18
 
17
- context 'with valid params' do
19
+ context 'with valid params' do # rubocop:disable Metrics/BlockLength
18
20
  context 'when apply_to_versions is false' do
19
21
  let(:params) { update_params }
20
22
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: approval_cycle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre
4
+ version: 0.1.1.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Farah Assaf
@@ -163,7 +163,6 @@ files:
163
163
  - app/services/approval_cycle/setup_updater.rb
164
164
  - app/views/layouts/approval_cycle/application.html.erb
165
165
  - config/routes.rb
166
- - db/migrate/20240723091230_enable_pg_trgm_extention.rb
167
166
  - db/migrate/20240723091231_create_approval_cycle_setups.rb
168
167
  - db/migrate/20240723142036_create_approval_cycle_approvers.rb
169
168
  - db/migrate/20240806080650_create_approval_cycle_watchers.rb
@@ -222,14 +221,13 @@ files:
222
221
  - spec/dummy/db/migrate/20241028115559_create_companies.rb
223
222
  - spec/dummy/db/migrate/20241028115633_create_dummy_users.rb
224
223
  - spec/dummy/db/migrate/20241030055459_create_dummy_requests.rb
225
- - spec/dummy/db/migrate/20250731094004_enable_pg_trgm_extention.rb
226
- - spec/dummy/db/migrate/20250731094005_create_approval_cycle_setups.rb
227
- - spec/dummy/db/migrate/20250731094006_create_approval_cycle_approvers.rb
228
- - spec/dummy/db/migrate/20250731094007_create_approval_cycle_watchers.rb
229
- - spec/dummy/db/migrate/20250731094008_create_approval_cycle_action_takers.rb
230
- - spec/dummy/db/migrate/20250731094009_create_approval_cycle_object_activities.rb
231
- - spec/dummy/db/migrate/20250731094010_create_approval_cycle_approvals.rb
232
- - spec/dummy/db/migrate/20250731094101_add_approval_cycle_to_configured_types.rb
224
+ - spec/dummy/db/migrate/20250731123034_create_approval_cycle_setups.rb
225
+ - spec/dummy/db/migrate/20250731123035_create_approval_cycle_approvers.rb
226
+ - spec/dummy/db/migrate/20250731123036_create_approval_cycle_watchers.rb
227
+ - spec/dummy/db/migrate/20250731123037_create_approval_cycle_action_takers.rb
228
+ - spec/dummy/db/migrate/20250731123038_create_approval_cycle_object_activities.rb
229
+ - spec/dummy/db/migrate/20250731123039_create_approval_cycle_approvals.rb
230
+ - spec/dummy/db/migrate/20250731123227_add_approval_cycle_to_configured_types.rb
233
231
  - spec/dummy/db/schema.rb
234
232
  - spec/dummy/log/development.log
235
233
  - spec/dummy/log/teast.log
@@ -252,6 +250,8 @@ files:
252
250
  - spec/factories/dummy_users.rb
253
251
  - spec/factories/setups.rb
254
252
  - spec/factories/watchers.rb
253
+ - spec/features/configurable_approval_statuses_demo_spec.rb
254
+ - spec/lib/approval_cycle/configuration_spec.rb
255
255
  - spec/models/approval_cycle/action_taker_spec.rb
256
256
  - spec/models/approval_cycle/approval_spec.rb
257
257
  - spec/models/approval_cycle/approver_spec.rb
@@ -334,14 +334,13 @@ test_files:
334
334
  - spec/dummy/db/migrate/20241028115559_create_companies.rb
335
335
  - spec/dummy/db/migrate/20241028115633_create_dummy_users.rb
336
336
  - spec/dummy/db/migrate/20241030055459_create_dummy_requests.rb
337
- - spec/dummy/db/migrate/20250731094004_enable_pg_trgm_extention.rb
338
- - spec/dummy/db/migrate/20250731094005_create_approval_cycle_setups.rb
339
- - spec/dummy/db/migrate/20250731094006_create_approval_cycle_approvers.rb
340
- - spec/dummy/db/migrate/20250731094007_create_approval_cycle_watchers.rb
341
- - spec/dummy/db/migrate/20250731094008_create_approval_cycle_action_takers.rb
342
- - spec/dummy/db/migrate/20250731094009_create_approval_cycle_object_activities.rb
343
- - spec/dummy/db/migrate/20250731094010_create_approval_cycle_approvals.rb
344
- - spec/dummy/db/migrate/20250731094101_add_approval_cycle_to_configured_types.rb
337
+ - spec/dummy/db/migrate/20250731123034_create_approval_cycle_setups.rb
338
+ - spec/dummy/db/migrate/20250731123035_create_approval_cycle_approvers.rb
339
+ - spec/dummy/db/migrate/20250731123036_create_approval_cycle_watchers.rb
340
+ - spec/dummy/db/migrate/20250731123037_create_approval_cycle_action_takers.rb
341
+ - spec/dummy/db/migrate/20250731123038_create_approval_cycle_object_activities.rb
342
+ - spec/dummy/db/migrate/20250731123039_create_approval_cycle_approvals.rb
343
+ - spec/dummy/db/migrate/20250731123227_add_approval_cycle_to_configured_types.rb
345
344
  - spec/dummy/db/schema.rb
346
345
  - spec/dummy/log/development.log
347
346
  - spec/dummy/log/teast.log
@@ -364,6 +363,8 @@ test_files:
364
363
  - spec/factories/dummy_users.rb
365
364
  - spec/factories/setups.rb
366
365
  - spec/factories/watchers.rb
366
+ - spec/features/configurable_approval_statuses_demo_spec.rb
367
+ - spec/lib/approval_cycle/configuration_spec.rb
367
368
  - spec/models/approval_cycle/action_taker_spec.rb
368
369
  - spec/models/approval_cycle/approval_spec.rb
369
370
  - spec/models/approval_cycle/approver_spec.rb
@@ -1,9 +0,0 @@
1
- class EnablePgTrgmExtention < ActiveRecord::Migration[7.0]
2
- def up
3
- enable_extension('pg_trgm') unless extensions.include?('pg_trgm')
4
- end
5
-
6
- def down
7
- disable_extension('pg_trgm') if extensions.include?('pg_trgm')
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- class EnablePgTrgmExtention < ActiveRecord::Migration[7.0]
2
- def up
3
- enable_extension('pg_trgm') unless extensions.include?('pg_trgm')
4
- end
5
-
6
- def down
7
- disable_extension('pg_trgm') if extensions.include?('pg_trgm')
8
- end
9
- end