diff --git a/app/controllers/frameworks/categorisations_controller.rb b/app/controllers/frameworks/categorisations_controller.rb new file mode 100644 index 000000000..69b8ac11e --- /dev/null +++ b/app/controllers/frameworks/categorisations_controller.rb @@ -0,0 +1,19 @@ +class Frameworks::CategorisationsController < Frameworks::ApplicationController + def edit + @framework = Frameworks::Framework.find(params[:framework_id]) + end + + def update + @framework = Frameworks::Framework.find(params[:framework_id]) + + @framework.update!(category_params) + + redirect_to @framework + end + +private + + def category_params + params.require(:frameworks_framework).permit(support_category_ids: []) + end +end diff --git a/app/models/frameworks/activity_event.rb b/app/models/frameworks/activity_event.rb new file mode 100644 index 000000000..cb19aba88 --- /dev/null +++ b/app/models/frameworks/activity_event.rb @@ -0,0 +1,7 @@ +class Frameworks::ActivityEvent < ApplicationRecord + include Frameworks::Activity + + def loaded_data + OpenStruct.new(**data, **activity_log_item.subject.try(:activity_event_data_for, self).presence || {}) + end +end diff --git a/app/models/frameworks/activity_log_item.rb b/app/models/frameworks/activity_log_item.rb index ac544a5fc..c3b1cd589 100644 --- a/app/models/frameworks/activity_log_item.rb +++ b/app/models/frameworks/activity_log_item.rb @@ -3,7 +3,9 @@ class Frameworks::ActivityLogItem < ApplicationRecord belongs_to :actor, polymorphic: true, optional: true belongs_to :subject, polymorphic: true, optional: true - delegated_type :activity, types: %w[Frameworks::ActivityLoggableVersion] + delegated_type :activity, types: %w[Frameworks::ActivityLoggableVersion Frameworks::ActivityEvent] + + default_scope { order("created_at DESC") } before_create do self.guid ||= Current.request_id diff --git a/app/models/frameworks/activity_loggable.rb b/app/models/frameworks/activity_loggable.rb index 349ae604d..531690cb7 100644 --- a/app/models/frameworks/activity_loggable.rb +++ b/app/models/frameworks/activity_loggable.rb @@ -14,6 +14,12 @@ module Frameworks::ActivityLoggable private def log_latest_version_in_activity_log + return unless previous_changes.any? + Frameworks::ActivityLogItem.create!(subject: self, activity: versions.last, activity_type: "Frameworks::ActivityLoggableVersion") end + + def log_activity_event(event, data = {}) + Frameworks::ActivityLogItem.create!(subject: self, activity: Frameworks::ActivityEvent.new(event:, data:)) + end end diff --git a/app/models/frameworks/framework.rb b/app/models/frameworks/framework.rb index f9623a18a..3cfa9c606 100644 --- a/app/models/frameworks/framework.rb +++ b/app/models/frameworks/framework.rb @@ -5,6 +5,7 @@ class Frameworks::Framework < ApplicationRecord include Sourceable include Presentable include ActivityLogPresentable + include ActivityEventLoggable include Filterable include Sortable @@ -12,7 +13,11 @@ class Frameworks::Framework < ApplicationRecord belongs_to :provider_contact, optional: true belongs_to :proc_ops_lead, class_name: "Support::Agent", optional: true belongs_to :e_and_o_lead, class_name: "Support::Agent", optional: true - belongs_to :support_category, class_name: "Support::Category", optional: true + + has_many :framework_categories + has_many :support_categories, through: :framework_categories, + after_add: :log_framework_category_added, + after_remove: :log_framework_category_removed validates :provider_id, presence: { message: "Please select a provider" }, on: :creation_form validates :provider_contact_id, presence: { message: "Please select a contact" }, on: :creation_form diff --git a/app/models/frameworks/framework/activity_event_loggable.rb b/app/models/frameworks/framework/activity_event_loggable.rb new file mode 100644 index 000000000..20c534b39 --- /dev/null +++ b/app/models/frameworks/framework/activity_event_loggable.rb @@ -0,0 +1,20 @@ +module Frameworks::Framework::ActivityEventLoggable + extend ActiveSupport::Concern + + def activity_event_data_for(activity_event) + case activity_event.event + when "framework_category_added", "framework_category_removed" + { support_category: Support::Category.find(activity_event.data["support_category_id"]) } + end + end + +protected + + def log_framework_category_added(category) + log_activity_event("framework_category_added", support_category_id: category.id) + end + + def log_framework_category_removed(category) + log_activity_event("framework_category_removed", support_category_id: category.id) + end +end diff --git a/app/models/frameworks/framework/filterable.rb b/app/models/frameworks/framework/filterable.rb index c26f0c24f..024a1648f 100644 --- a/app/models/frameworks/framework/filterable.rb +++ b/app/models/frameworks/framework/filterable.rb @@ -4,7 +4,7 @@ module Frameworks::Framework::Filterable included do scope :by_status, ->(statuses) { where(status: Array(statuses)) } scope :by_provider, ->(provider_ids) { where(provider_id: Array(provider_ids)) } - scope :by_category, ->(category_ids) { where(support_category_id: Array(category_ids)) } + scope :by_category, ->(category_ids) { joins(:framework_categories).where(framework_categories: { support_category_id: Array(category_ids) }) } scope :by_e_and_o_lead, ->(e_and_o_lead_ids) { where(e_and_o_lead_id: Array(e_and_o_lead_ids)) } scope :by_proc_ops_lead, ->(proc_ops_lead_ids) { where(proc_ops_lead_id: Array(proc_ops_lead_ids)) } scope :by_provider_contact, ->(provider_contact_ids) { where(provider_contact_id: Array(provider_contact_ids)) } diff --git a/app/models/frameworks/framework/filtering.rb b/app/models/frameworks/framework/filtering.rb index e31eca699..e90906ccb 100644 --- a/app/models/frameworks/framework/filtering.rb +++ b/app/models/frameworks/framework/filtering.rb @@ -22,8 +22,7 @@ def results end def available_category_options - Support::Category.order("title ASC").where(id: Frameworks::Framework.pluck(:support_category_id)) - .map { |category| [category.title, category.id] } + Support::Category.order("title ASC").where(id: Frameworks::FrameworkCategory.pluck(:support_category_id)).pluck(:title, :id) end def available_provider_filter_options diff --git a/app/models/frameworks/framework/presentable.rb b/app/models/frameworks/framework/presentable.rb index a697c1b17..6971d8b5f 100644 --- a/app/models/frameworks/framework/presentable.rb +++ b/app/models/frameworks/framework/presentable.rb @@ -21,8 +21,8 @@ def provider_framework_owner_email provider_contact&.email end - def category_name - support_category&.title + def category_names + support_categories.pluck(:title).join(", ") end def proc_ops_lead_name diff --git a/app/models/frameworks/framework/sortable.rb b/app/models/frameworks/framework/sortable.rb index bfe56710c..42518e761 100644 --- a/app/models/frameworks/framework/sortable.rb +++ b/app/models/frameworks/framework/sortable.rb @@ -2,7 +2,7 @@ module Frameworks::Framework::Sortable extend ActiveSupport::Concern included do - scope :sort_by_updated, ->(direction = "descending") { order("updated_at #{safe_direction(direction)}") } + scope :sort_by_updated, ->(direction = "descending") { order("frameworks_frameworks.updated_at #{safe_direction(direction)}") } scope :sort_by_dfe_start_date, ->(direction = "descending") { order("dfe_start_date #{safe_direction(direction)}") } scope :sort_by_dfe_end_date, ->(direction = "descending") { order("dfe_end_date #{safe_direction(direction)}") } scope :sort_by_provider_start_date, ->(direction = "descending") { order("provider_start_date #{safe_direction(direction)}") } diff --git a/app/models/frameworks/framework_category.rb b/app/models/frameworks/framework_category.rb new file mode 100644 index 000000000..2536017b3 --- /dev/null +++ b/app/models/frameworks/framework_category.rb @@ -0,0 +1,4 @@ +class Frameworks::FrameworkCategory < ApplicationRecord + belongs_to :support_category, class_name: "Support::Category" + belongs_to :framework +end diff --git a/app/views/frameworks/activity_log_items/activity/_activity_event.html.erb b/app/views/frameworks/activity_log_items/activity/_activity_event.html.erb new file mode 100644 index 000000000..0082550d6 --- /dev/null +++ b/app/views/frameworks/activity_log_items/activity/_activity_event.html.erb @@ -0,0 +1,4 @@ +<%= render "frameworks/activity_log_items/activity/activity_event/#{activity_log_item.activity.event}", + activity_log_item:, + activity: activity_log_item.activity, + subject: activity_log_item.subject %> diff --git a/app/views/frameworks/activity_log_items/activity/_activity_loggable_version.erb b/app/views/frameworks/activity_log_items/activity/_activity_loggable_version.html.erb similarity index 100% rename from app/views/frameworks/activity_log_items/activity/_activity_loggable_version.erb rename to app/views/frameworks/activity_log_items/activity/_activity_loggable_version.html.erb diff --git a/app/views/frameworks/activity_log_items/activity/activity_event/_framework_category_added.html.erb b/app/views/frameworks/activity_log_items/activity/activity_event/_framework_category_added.html.erb new file mode 100644 index 000000000..8ae6f6f22 --- /dev/null +++ b/app/views/frameworks/activity_log_items/activity/activity_event/_framework_category_added.html.erb @@ -0,0 +1 @@ +Added category "<%= activity.loaded_data.support_category.title %>" to framework diff --git a/app/views/frameworks/activity_log_items/activity/activity_event/_framework_category_removed.html.erb b/app/views/frameworks/activity_log_items/activity/activity_event/_framework_category_removed.html.erb new file mode 100644 index 000000000..2667604a5 --- /dev/null +++ b/app/views/frameworks/activity_log_items/activity/activity_event/_framework_category_removed.html.erb @@ -0,0 +1 @@ +Removed category "<%= activity.loaded_data.support_category.title %>" from framework diff --git a/app/views/frameworks/categorisations/edit.html.erb b/app/views/frameworks/categorisations/edit.html.erb new file mode 100644 index 000000000..c8d074cac --- /dev/null +++ b/app/views/frameworks/categorisations/edit.html.erb @@ -0,0 +1,22 @@ +<%= content_for :title, "GHBS | Frameworks | Edit Framework Categories" %> + +
+