diff --git a/app/models/asset.rb b/app/models/asset.rb index 3f221346a..6fa14f728 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -8,6 +8,7 @@ class Asset < ApplicationRecord include ActiveStorageConcerns include ActiveStorageHelper include VersionedAttachments + include ObservableModel require 'tempfile' # Lock duration set to 30 minutes @@ -475,4 +476,8 @@ class Asset < ApplicationRecord def reset_file_processing self.file_processing = false end + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(step, last_modified_by || created_by).call + end end diff --git a/app/models/checklist.rb b/app/models/checklist.rb index 15580506f..0505dc9e1 100644 --- a/app/models/checklist.rb +++ b/app/models/checklist.rb @@ -1,5 +1,6 @@ class Checklist < ApplicationRecord include SearchableModel + include ObservableModel auto_strip_attributes :name, nullify: false validates :name, @@ -57,4 +58,10 @@ class Checklist < ApplicationRecord new_checklist end end + + private + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(step, last_modified_by || created_by).call + end end diff --git a/app/models/checklist_item.rb b/app/models/checklist_item.rb index 17482023a..97998ccb7 100644 --- a/app/models/checklist_item.rb +++ b/app/models/checklist_item.rb @@ -1,4 +1,5 @@ class ChecklistItem < ApplicationRecord + include ObservableModel attr_accessor :with_paragraphs @@ -22,6 +23,7 @@ class ChecklistItem < ApplicationRecord class_name: 'User', optional: true + after_create :run_observers # conditional touch excluding checked updates after_destroy :touch_checklist after_save :touch_checklist @@ -76,4 +78,8 @@ class ChecklistItem < ApplicationRecord checklist.touch # rubocop:enable Rails/SkipsModelValidations end + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(checklist.step, last_modified_by || created_by).call + end end diff --git a/app/models/form_field_value.rb b/app/models/form_field_value.rb index 1412219cd..c1cf93054 100644 --- a/app/models/form_field_value.rb +++ b/app/models/form_field_value.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class FormFieldValue < ApplicationRecord + include ObservableModel + belongs_to :form_response belongs_to :form_field belongs_to :created_by, class_name: 'User' @@ -44,4 +46,8 @@ class FormFieldValue < ApplicationRecord errors.add(:value, :not_unique_latest) end + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(form_response.step, created_by).call + end end diff --git a/app/models/result.rb b/app/models/result.rb index a93a4dcce..378677fce 100644 --- a/app/models/result.rb +++ b/app/models/result.rb @@ -44,6 +44,8 @@ class Result < ApplicationRecord CleanupUserSettingsJob.perform_later('result_states', id) end + after_create :run_observers + def self.search(user, include_archived, query = nil, @@ -196,4 +198,10 @@ class Result < ApplicationRecord def delete_step_results step_results.destroy_all end + + private + + def run_observers + AutomationObservers::ResultCreateAutomationObserver.new(my_module, user).call + end end diff --git a/app/models/step.rb b/app/models/step.rb index 7c66f94e2..547d5d19e 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -22,6 +22,7 @@ class Step < ApplicationRecord before_validation :set_completed_on, if: :completed_changed? before_save :set_last_modified_by + after_create :run_observers before_destroy :cascade_before_destroy after_destroy :adjust_positions_after_destroy, unless: -> { skip_position_adjust } @@ -187,7 +188,14 @@ class Step < ApplicationRecord private def run_observers - AutomationObservers::AllCheckedStepsAutomationObserver.new(my_module, last_modified_by).call if saved_change_to_completed? && completed + return unless protocol.in_module? + + if saved_change_to_completed? + AutomationObservers::CompletedStepChangeAutomationObserver.new(my_module, last_modified_by).call if completed + AutomationObservers::AllCompletedStepsAutomationObserver.new(my_module, last_modified_by).call + end + + AutomationObservers::ProtocolContentChangedAutomationObserver.new(self, last_modified_by).call end def duplicate_table(new_step, user, table) diff --git a/app/models/step_comment.rb b/app/models/step_comment.rb index fabf999ef..a37959ac3 100644 --- a/app/models/step_comment.rb +++ b/app/models/step_comment.rb @@ -1,7 +1,10 @@ # frozen_string_literal: true class StepComment < Comment + include ObservableModel + before_create :fill_unseen_by + after_create :run_observers belongs_to :step, foreign_key: :associated_id, inverse_of: :step_comments @@ -16,4 +19,8 @@ class StepComment < Comment def fill_unseen_by self.unseen_by += step.protocol.my_module.experiment.project.users.where.not(id: user.id).pluck(:id) end + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(step, last_modified_by || user).call + end end diff --git a/app/models/step_orderable_element.rb b/app/models/step_orderable_element.rb index 125b8d578..0ecf9786a 100644 --- a/app/models/step_orderable_element.rb +++ b/app/models/step_orderable_element.rb @@ -4,6 +4,7 @@ class StepOrderableElement < ApplicationRecord validates :position, uniqueness: { scope: :step } validate :check_step_relations + after_create :run_observers around_destroy :decrement_following_elements_positions belongs_to :step, inverse_of: :step_orderable_elements, touch: true @@ -26,4 +27,8 @@ class StepOrderableElement < ApplicationRecord step.normalize_elements_position end end + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(step, step.last_modified_by).call + end end diff --git a/app/models/step_text.rb b/app/models/step_text.rb index 9ae6cabf1..556c11653 100644 --- a/app/models/step_text.rb +++ b/app/models/step_text.rb @@ -3,6 +3,7 @@ class StepText < ApplicationRecord include TinyMceImages include ActionView::Helpers::TextHelper + include ObservableModel auto_strip_attributes :name, nullify: false validates :name, length: { maximum: Constants::NAME_MAX_LENGTH } @@ -38,4 +39,10 @@ class StepText < ApplicationRecord new_step_text end end + + private + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(step, step.last_modified_by).call + end end diff --git a/app/models/table.rb b/app/models/table.rb index 2f80a3c9b..0c18a9450 100644 --- a/app/models/table.rb +++ b/app/models/table.rb @@ -3,6 +3,7 @@ class Table < ApplicationRecord include SearchableModel include TableHelper + include ObservableModel auto_strip_attributes :name, nullify: false validates :name, @@ -102,4 +103,8 @@ class Table < ApplicationRecord end end end + + def run_observers + AutomationObservers::ProtocolContentChangedAutomationObserver.new(step, step&.last_modified_by).call + end end diff --git a/app/services/automation_observers/all_checked_steps_automation_observer.rb b/app/services/automation_observers/all_completed_steps_automation_observer.rb similarity index 96% rename from app/services/automation_observers/all_checked_steps_automation_observer.rb rename to app/services/automation_observers/all_completed_steps_automation_observer.rb index ce2b0cd47..afc5e7b2b 100644 --- a/app/services/automation_observers/all_checked_steps_automation_observer.rb +++ b/app/services/automation_observers/all_completed_steps_automation_observer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module AutomationObservers - class AllCheckedStepsAutomationObserver + class AllCompletedStepsAutomationObserver def initialize(my_module, user) @my_module = my_module @user = user diff --git a/app/services/automation_observers/completed_step_change_automation_observer.rb b/app/services/automation_observers/completed_step_change_automation_observer.rb new file mode 100644 index 000000000..26390d91c --- /dev/null +++ b/app/services/automation_observers/completed_step_change_automation_observer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module AutomationObservers + class CompletedStepChangeAutomationObserver + def initialize(my_module, user) + @my_module = my_module + @user = user + end + + def call + return unless @my_module.team.settings.dig('team_automation_settings', 'step_marked_as_completed') + return unless @my_module.my_module_status.initial_status? + + previous_status_id = @my_module.my_module_status.id + @my_module.update!(my_module_status: @my_module.my_module_status.next_status) + + Activities::CreateActivityService + .call(activity_type: :automation_task_status_changed, + owner: @user, + team: @my_module.team, + project: @my_module.project, + subject: @my_module, + message_items: { + my_module: @my_module.id, + my_module_status_old: previous_status_id, + my_module_status_new: @my_module.my_module_status.id + }) + end + end +end diff --git a/app/services/automation_observers/protocol_content_changed_automation_observer.rb b/app/services/automation_observers/protocol_content_changed_automation_observer.rb new file mode 100644 index 000000000..d23b5177e --- /dev/null +++ b/app/services/automation_observers/protocol_content_changed_automation_observer.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module AutomationObservers + class ProtocolContentChangedAutomationObserver + def initialize(step, user) + @step = step + @my_module = step&.my_module + @user = user + end + + def call + return if @step.blank? + return unless @step.protocol.in_module? + return unless @my_module.team.settings.dig('team_automation_settings', 'protocol_content_added') + return unless @my_module.my_module_status.initial_status? + + previous_status_id = @my_module.my_module_status.id + @my_module.update!(my_module_status: @my_module.my_module_status.next_status) + + Activities::CreateActivityService + .call(activity_type: :automation_task_status_changed, + owner: @user, + team: @my_module.team, + project: @my_module.project, + subject: @my_module, + message_items: { + my_module: @my_module.id, + my_module_status_old: previous_status_id, + my_module_status_new: @my_module.my_module_status.id + }) + end + end +end diff --git a/app/services/automation_observers/result_create_automation_observer.rb b/app/services/automation_observers/result_create_automation_observer.rb new file mode 100644 index 000000000..765fcda23 --- /dev/null +++ b/app/services/automation_observers/result_create_automation_observer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module AutomationObservers + class ResultCreateAutomationObserver + def initialize(my_module, user) + @my_module = my_module + @user = user + end + + def call + return @my_module.team.settings.dig('team_automation_settings', 'task_result_added') unless @my_module.team.settings.dig('team_automation_settings', 'task_result_added') + return unless @my_module.my_module_status.initial_status? + + previous_status_id = @my_module.my_module_status.id + @my_module.update!(my_module_status: @my_module.my_module_status.next_status) + + Activities::CreateActivityService + .call(activity_type: :automation_task_status_changed, + owner: @user, + team: @my_module.team, + project: @my_module.project, + subject: @my_module, + message_items: { + my_module: @my_module.id, + my_module_status_old: previous_status_id, + my_module_status_new: @my_module.my_module_status.id + }) + end + end +end