dcidev_approval 0.0.9 → 0.0.13

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 (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