dcidev_approval 0.0.9 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -5
  3. data/lib/dcidev_approval.rb +145 -165
  4. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e97350e7fc396ea5b6badf639f46c97c256de119290e7f4cf209a29b55c13fc2
4
- data.tar.gz: 32378050bd803f53adf02652f4d5502b871e2ea6ce7aed380970a395d1562761
3
+ metadata.gz: ceacb6241a269f4b1c40dc7f83d1fb245619456759e9814514cbdb694365b757
4
+ data.tar.gz: d3fe771c426cd90a58d1f8bb83658652d42081f1fdda5e53a1f767196d9346b0
5
5
  SHA512:
6
- metadata.gz: 59b9cf658199b5dd33f76c3eb22f6d302718a908f220d986a46d9fe90a28f82b490fbc31993a36193f555cadcd5bed77ef91f73c8276a513af210db61aa7f53b
7
- data.tar.gz: f800249db88dacaafadfaa400946f602753c558288e6f0671c25c780de21b3fd4660d4e4954472ec8d1264fde3b3214d9c24dee755284224d2cbb146979d85de
6
+ metadata.gz: 1a85f826b582a4e27af4c43136024b7c033fbaf89a6f97fa93b459fde6de38c08fbfba026a96d48d80e5b5a8b0baef675af25a52a1baa411dbc432bde14a7ad0
7
+ data.tar.gz: 0a2a2d68986cd8285614bad0531030c064e759139da4180929c08b39ff23515505f3a87254e80c2f7e897f96ba54e890773ad2a8a9728b267a1566b1485e3528
data/README.md CHANGED
@@ -4,8 +4,11 @@
4
4
  ```ruby
5
5
  class AddStatusToProduk < ActiveRecord::Migration[6.0]
6
6
  def change
7
- add_column :produk, :status, :string
8
- add_column :produk, :change_status, :string
7
+ change_column :model do |t|
8
+ t.string :status
9
+ t.string :change_status
10
+ t.json :data_changes
11
+ end
9
12
  end
10
13
  end
11
14
  ```
@@ -18,8 +21,6 @@ CHANGE_STATUS = %w(pending_delete pending_update).freeze
18
21
  enum change_status: CHANGE_STATUS.zip(CHANGE_STATUS).to_h, _prefix: true
19
22
  ```
20
23
 
21
-
22
-
23
24
  ##### 2. Format your `Agent` and `Role` with one-many relationship.
24
25
  ##### 3. Declare instance method `is_admin?` to `Agent` to find out whether an agent is an admin or not
25
26
 
@@ -56,8 +57,23 @@ Explanation
56
57
  * `current_user`: the agent responsible for the changes
57
58
  * `bypass`: boolean value to toogle the approval system. If not sent, the default value is `true`
58
59
 
59
- To track changes peformed to a record, call
60
+ To track changes peformed to a record, call `instance_model.audit_trails`
61
+
62
+ # Approval
63
+ To approve / reject changes, call `approval(params)`.
64
+ You MUST use `status` as the param name otherwise it wont work.
65
+ ```ruby
66
+ params do
67
+ requires :status, type: String, values: %w[approved rejected]
68
+ end
69
+ post "/approval/:id" do
70
+ @produk.approval(params, current_user)
71
+ present :produk, @produk
72
+ end
73
+ ```
74
+
60
75
  # Callbacks
76
+
61
77
  To execute code before/after the CRUD, include module `DcidevApproval` in `ApplicationRecord` and peform overide and or overload on it's child model.
62
78
 
63
79
  `app/models/application_record.rb`
@@ -1,170 +1,150 @@
1
- module DcidevApproval
2
- def self.included base
3
- base.send :include, InstanceMethods
4
- base.extend ClassMethods
5
- end
6
-
7
- module InstanceMethods
8
-
9
- def changes_present?(changes)
10
- present = false
11
- changes.each do |k, v|
12
- begin
13
- if eval("self.#{k}") != v
14
- present = true
15
- break
16
- end
17
- rescue => _
18
- end
19
- end
20
- return present
21
- end
22
-
23
- def waiting_approval?
24
- %w[pending_update pending_delete].include?(self.change_status) || self.status == "waiting"
25
- end
26
-
27
- def pending_insert?
28
- self.change_status.nil? && %w[waiting rejected].include?(self.status)
29
- end
30
-
31
- def pending_update?
32
- self.change_status == "pending_update"
33
- end
34
-
35
- def pending_delete?
36
- self.change_status == "pending_delete"
37
- end
38
-
39
- def approved?
40
- self.status == "approved" || self.change_status.nil?
41
- end
42
-
43
- def rejected?
44
- self.status == "rejected"
45
- end
46
-
47
- def waiting?
48
- self.status == "waiting"
49
- end
50
-
51
- def last_modified_by
52
- # p self.audit_trail
53
- if self.try(:change_status).present? && self.try(:change_status) == 'pending_delete'
54
- log = self.activity_logs.where("activity LIKE '%delete%'").limit(1).order(created_at: :desc).try(:first)
55
- else
56
- log = self.activity_logs.where("activity LIKE '%edit%'").limit(1).order(created_at: :desc).try(:first)
57
- end
58
- {
59
- modified_by: log.present? ? log.try(:agent).try(:name).to_s + " (#{log.try(:agent).try(:username).to_s} | #{log.try(:agent).try(:roles).try(:first).try(:name)})" : nil,
60
- modified_at: log.present? ? log.try(:created_at) || self.try(:updated_at) || self.try(:created_at) : nil
61
- }
62
- end
63
-
64
- def created_by
65
- log = self.activity_logs.try(:first)
66
- {
67
- created_by: log.present? && log.try(:agent).try(:name).present? ? log.try(:agent).try(:name).to_s + " (#{log.try(:agent).try(:username).to_s} | #{log.try(:agent).try(:roles).try(:first).try(:name)})" : "System",
68
- created_at: self.try(:created_at) || log.try(:created_at)
69
- }
70
- end
71
-
72
- def last_approved_by
73
- last_approve = self.activity_logs.where("activity LIKE '%approv%'").limit(1).order(created_at: :desc).try(:first)
74
- last_entry = self.activity_logs.last
75
- {
76
- approved_by: last_approve.try(:id) == last_entry.try(:id) ? last_approve.try(:agent).try(:name).to_s + " (#{last_approve.try(:agent).try(:username).to_s} | #{last_approve.try(:agent).try(:roles).try(:first).try(:name)})" : nil,
77
- approved_at: last_approve.try(:id) == last_entry.try(:id) ? last_approve.try(:created_at) : nil
78
- }
79
- end
80
-
81
- def approve_changes
82
-
83
- if self.change_status.nil? && %w[waiting rejected].include?(self.status)
84
- raise self.errors.full_messages.join(", ") unless self.update(status: :approved, data_changes: nil, change_status: nil)
85
- # ActivityLog.write("Approve insert to #{self.class.to_s}", request, agent, menu, self) if params.log
86
- # self.delay(queue: "reorder_#{self.id}", priority: 0).reorder if self.class.column_names.include?("view_order")
87
-
88
- end
89
- if self.change_status == "pending_update"
90
- raise self.errors.full_messages.join(", ") unless self.update_by_params(self.data_changes, false)
91
- raise self.errors.full_messages.join(", ") unless self.update(status: :approved, data_changes: nil, change_status: nil)
92
- # ActivityLog.write("Approve update to #{self.class.to_s}", request, agent, menu, self) if params.log
93
- # self.delay(queue: "reorder_#{self.id}", priority: 0).reorder if self.class.column_names.include?("view_order")
1
+ # frozen_string_literal: true
94
2
 
95
- elsif self.change_status == "pending_delete"
96
- raise self.errors.full_messages.join(", ") unless self.update(change_status: nil, data_changes: nil)
97
- ActiveRecord::Base.transaction do
98
- # ActivityLog.write("Approve delete to #{self.class.to_s}", request, agent, menu, self) if params.log
99
- self.try(:destroy)
3
+ module DcidevApproval
4
+ def self.included(base)
5
+ base.send :include, InstanceMethods
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module InstanceMethods
10
+ def changes_present?(changes)
11
+ present = false
12
+ changes.each do |k, v|
13
+ if eval("self.#{k}") != v
14
+ present = true
15
+ break
16
+ end
17
+ rescue StandardError => _e
18
+ end
19
+ present
20
+ end
21
+
22
+ def waiting_approval?
23
+ %w[pending_update pending_delete].include?(change_status) || status == 'waiting'
24
+ end
25
+
26
+ def pending_insert?
27
+ change_status.nil? && %w[waiting rejected].include?(status)
28
+ end
29
+
30
+ def pending_update?
31
+ change_status == 'pending_update'
32
+ end
33
+
34
+ def pending_delete?
35
+ change_status == 'pending_delete'
36
+ end
37
+
38
+ def approved?
39
+ status == 'approved' || change_status.nil?
40
+ end
41
+
42
+ def rejected?
43
+ status == 'rejected'
44
+ end
45
+
46
+ def waiting?
47
+ status == 'waiting'
48
+ end
49
+
50
+ def last_modified_by
51
+ log = audit_trails.where(activity_type: %w[update delete]).limit(1).try(:first)
52
+ {
53
+ modified_by: log.present? ? log.try(:agent).try(:name).to_s + " (#{log.try(:agent).try(:roles).try(:first).try(:name)})" : nil,
54
+ modified_at: log.present? ? log.try(:created_at) || try(:updated_at) || try(:created_at) : nil
55
+ }
56
+ end
57
+
58
+ def created_by
59
+ log = audit_trails(:asc).where(activity_type: :create).limit(1).try(:first)
60
+ {
61
+ created_by: log.present? && log.try(:agent).try(:name).present? ? log.try(:agent).try(:name).to_s + " (#{log.try(:agent_role).try(:name)})" : 'System',
62
+ created_at: self.try(:created_at) || log.try(:created_at)
63
+ }
64
+ end
65
+
66
+ def last_approved_by
67
+ last_approve = audit_trails.where(approval: true).limit(1).try(:first)
68
+ last_entry = audit_trails.limit(1).try(:first)
69
+ {
70
+ approved_by: last_approve.try(:id) == last_entry.try(:id) ? last_approve.try(:agent).try(:name).to_s + " (#{last_approve.try(:agent_role).try(:name)})" : nil,
71
+ approved_at: last_approve.try(:id) == last_entry.try(:id) ? last_approve.try(:created_at) : nil
72
+ }
73
+ end
74
+
75
+ def approve_changes
76
+ if change_status.nil? && %w[waiting rejected].include?(status) && !update(status: :approved, data_changes: nil, change_status: nil)
77
+ raise errors.full_messages.join(', ')
78
+ end
79
+
80
+ case change_status
81
+ when 'pending_update'
82
+ raise errors.full_messages.join(', ') unless update_by_params(data_changes, false)
83
+ raise errors.full_messages.join(', ') unless update(status: :approved, data_changes: nil, change_status: nil)
84
+ when 'pending_delete'
85
+ destroy
86
+ end
87
+ end
88
+
89
+ def delete_changes
90
+ raise errors.full_messages.join(', ') unless update(data_changes: nil, change_status: nil, status: status == 'waiting' ? :rejected : :approved)
91
+ end
92
+
93
+ def edit_data(params, agent, bypass = true)
94
+ raise 'data still waiting for approval' if waiting_approval?
95
+
96
+ if bypass
97
+ raise errors.full_messages.join(', ') unless update_by_params(params, false)
98
+ elsif changes_present?(params)
99
+ ActiveRecord::Base.transaction do
100
+ data = agent.is_admin? || status == 'waiting' ? params :{ change_status: :pending_update, data_changes: agent.is_admin? ? nil : params }
101
+ raise errors.full_messages.join(', ') unless update_by_params(data, false)
102
+ end
103
+ end
104
+ yield self
105
+ end
106
+
107
+ def approval(params)
108
+ case params.status
109
+ when 'approved'
110
+ approve_changes
111
+ when 'rejected'
112
+ delete_changes
113
+ end
114
+ yield self
115
+ end
116
+
117
+ def delete_data(agent, bypass = true)
118
+ raise 'data still waiting for approval' if waiting_approval?
119
+
120
+ if bypass || agent.is_admin?
121
+ ActiveRecord::Base.transaction do
122
+ raise errors.full_messages.join(', ') unless destroy
123
+ end
124
+ else
125
+ raise errors.full_messages.join(', ') unless update(change_status: :pending_delete)
126
+ end
127
+ yield true
100
128
  end
101
- end
102
- end
103
-
104
- def delete_changes
105
- # return unless %w[pending_update pending_delete].include? self.change_status
106
- raise self.errors.full_messages.join(", ") unless self.update(data_changes: nil, change_status: nil, status: self.status == "waiting" ? :rejected : :approved)
107
- # ActivityLog.write("Reject changes to #{self.class.to_s}", request, agent, menu, self) if params.log
108
- end
109
-
110
- def edit_data(params, agent, bypass = true)
111
- raise "data still waiting for approval" if self.waiting_approval?
112
- if bypass
113
- raise self.errors.full_messages.join(", ") unless self.update_by_params(params, false)
114
- # ActivityLog.write("Edit #{self.class.to_s}", request, agent, menu, self) if params.log
115
- else
116
- if self.changes_present?(params)
117
- ActiveRecord::Base.transaction do
118
- data = (agent.is_admin? || self.status == "waiting") ? params : { change_status: :pending_update, data_changes: agent.is_admin? ? nil : params }
119
- raise self.errors.full_messages.join(", ") unless self.update_by_params(data, false)
120
- end
121
- # ActivityLog.write("#{agent.is_admin? ? nil : "Request "}Edit #{self.class.to_s}", request, agent, menu, self) if params.log
122
- end
123
- end
124
- yield self
125
- end
126
-
127
- def approval(params)
128
- if params.status == "approved"
129
- self.approve_changes
130
- elsif params.status == "rejected"
131
- self.delete_changes
132
- end
133
- yield self
134
- end
135
-
136
- def delete_data(agent, bypass = true)
137
- raise "data still waiting for approval" if self.waiting_approval?
138
- if bypass || agent.is_admin?
139
- ActiveRecord::Base.transaction do
140
- # ActivityLog.write("Delete #{self.class.to_s}", request, agent, menu, self) if params.log
141
- raise self.errors.full_messages.join(", ") unless self.destroy
142
- end
143
- else
144
- raise self.errors.full_messages.join(", ") unless self.update(change_status: :pending_delete)
145
- # ActivityLog.write("Request Delete #{self.class.to_s}", request, agent, menu, self) if params.log
146
- end
147
- yield true
148
129
  end
149
- end
150
-
151
- module ClassMethods
152
- def create_data(params, agent, bypass = true)
153
- if bypass
154
- ActiveRecord::Base.transaction do
155
- data = params.merge!({ status: :approved })
156
- d = self.new_from_params(data)
157
- raise d.errors.full_messages.join(", ") unless d.save
158
- yield d
159
- # ActivityLog.write("#{agent.is_admin? ? nil : "Request "} Add #{self.to_s}", request, agent, menu, d) if params.log
160
- end
161
- else
162
- d = self.new_from_params(params)
163
- d.status = agent.is_admin? ? :approved : :waiting
164
- raise d.errors.full_messages.join(", ") unless d.save
165
- yield d
166
- end
130
+
131
+ module ClassMethods
132
+ def create_data(params, agent, bypass = true)
133
+ if bypass
134
+ ActiveRecord::Base.transaction do
135
+ data = params.merge!({ status: :approved })
136
+ d = new_from_params(data)
137
+ raise d.errors.full_messages.join(', ') unless d.save
138
+
139
+ yield d
140
+ end
141
+ else
142
+ d = new_from_params(params)
143
+ d.status = agent.is_admin? ? :approved : :waiting
144
+ raise d.errors.full_messages.join(', ') unless d.save
145
+
146
+ yield d
147
+ end
148
+ end
167
149
  end
168
- end
169
150
  end
170
-
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dcidev_approval
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Punto Damar P
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-09 00:00:00.000000000 Z
11
+ date: 2022-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dcidev_active_record
@@ -51,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
51
51
  - !ruby/object:Gem::Version
52
52
  version: '0'
53
53
  requirements: []
54
- rubygems_version: 3.1.2
54
+ rubygems_version: 3.0.3.1
55
55
  signing_key:
56
56
  specification_version: 4
57
57
  summary: Logic for implementing record changes approval