canvas-lms/lib/canvas/live_events.rb

974 lines
34 KiB
Ruby

# frozen_string_literal: true
#
# Copyright (C) 2015 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
module Canvas::LiveEvents
def self.post_event_stringified(event_name, payload, context = nil)
ctx = LiveEvents.get_context || {}
payload.compact! if ctx.dig(:compact_live_events)&.present?
StringifyIds.recursively_stringify_ids(payload)
StringifyIds.recursively_stringify_ids(context)
LiveEvents.post_event(
event_name: event_name,
payload: payload,
time: Time.zone.now,
context: context
)
end
def self.amended_context(canvas_context)
ctx = LiveEvents.get_context || {}
return ctx unless canvas_context
ctx = ctx.merge({
context_type: canvas_context.class.to_s,
context_id: canvas_context.global_id
})
if canvas_context.respond_to?(:root_account)
ctx.merge!({
root_account_id: canvas_context.root_account.try(:global_id),
root_account_uuid: canvas_context.root_account.try(:uuid),
root_account_lti_guid: canvas_context.root_account.try(:lti_guid),
})
end
ctx
end
def self.conversation_created(conversation)
post_event_stringified('conversation_created', {
conversation_id: conversation.id,
updated_at: conversation.updated_at
})
end
def self.conversation_forwarded(conversation)
post_event_stringified('conversation_forwarded', {
conversation_id: conversation.id,
updated_at: conversation.updated_at
},
amended_context(nil))
end
def self.get_course_data(course)
{
course_id: course.global_id,
uuid: course.uuid,
account_id: course.global_account_id,
name: course.name,
created_at: course.created_at,
updated_at: course.updated_at,
workflow_state: course.workflow_state
}
end
def self.course_created(course)
post_event_stringified('course_created', get_course_data(course))
end
def self.course_updated(course)
post_event_stringified('course_updated', get_course_data(course))
end
def self.course_syllabus_updated(course, old_syllabus_body)
post_event_stringified('syllabus_updated', {
course_id: course.global_id,
syllabus_body: LiveEvents.truncate(course.syllabus_body),
old_syllabus_body: LiveEvents.truncate(old_syllabus_body)
})
end
def self.conversation_message_created(conversation_message)
post_event_stringified('conversation_message_created', {
author_id: conversation_message.author_id,
conversation_id: conversation_message.conversation_id,
created_at: conversation_message.created_at,
message_id: conversation_message.id
})
end
def self.discussion_entry_created(entry)
post_event_stringified('discussion_entry_created', get_discussion_entry_data(entry))
end
def self.discussion_entry_submitted(entry, assignment_id, submission_id)
payload = get_discussion_entry_data(entry)
payload[:assignment_id] = assignment_id unless assignment_id.nil?
payload[:submission_id] = submission_id unless submission_id.nil?
post_event_stringified('discussion_entry_submitted', payload)
end
def self.get_discussion_entry_data(entry)
payload = {
user_id: entry.user_id,
created_at: entry.created_at,
discussion_entry_id: entry.id,
discussion_topic_id: entry.discussion_topic_id,
text: LiveEvents.truncate(entry.message)
}
payload[:parent_discussion_entry_id] = entry.parent_id if entry.parent_id
payload
end
def self.discussion_topic_created(topic)
post_event_stringified('discussion_topic_created', get_discussion_topic_data(topic))
end
def self.discussion_topic_updated(topic)
post_event_stringified('discussion_topic_updated', get_discussion_topic_data(topic))
end
def self.get_discussion_topic_data(topic)
{
discussion_topic_id: topic.global_id,
is_announcement: topic.is_announcement,
title: LiveEvents.truncate(topic.title),
body: LiveEvents.truncate(topic.message),
assignment_id: topic.assignment_id,
context_id: topic.context_id,
context_type: topic.context_type,
workflow_state: topic.workflow_state,
lock_at: topic.lock_at,
updated_at: topic.updated_at
}
end
def self.account_notification_created(notification)
post_event_stringified('account_notification_created', {
account_notification_id: notification.global_id,
subject: LiveEvents.truncate(notification.subject),
message: LiveEvents.truncate(notification.message),
icon: notification.icon,
start_at: notification.start_at,
end_at: notification.end_at,
})
end
def self.get_group_membership_data(membership)
{
group_membership_id: membership.global_id,
user_id: membership.global_user_id,
group_id: membership.global_group_id,
group_name: membership.group.name,
group_category_id: membership.group.global_group_category_id,
group_category_name: membership.group.group_category.try(:name),
workflow_state: membership.workflow_state
}
end
def self.group_membership_created(membership)
post_event_stringified('group_membership_created', get_group_membership_data(membership))
end
def self.group_membership_updated(membership)
post_event_stringified('group_membership_updated', get_group_membership_data(membership))
end
def self.get_group_category_data(group_category)
{
group_category_id: group_category.global_id,
group_category_name: group_category.name,
context_id: group_category.context_id,
context_type: group_category.context_type,
group_limit: group_category.group_limit
}
end
def self.group_category_updated(group_category)
post_event_stringified('group_category_updated', get_group_category_data(group_category))
end
def self.group_category_created(group_category)
post_event_stringified('group_category_created', get_group_category_data(group_category))
end
def self.get_group_data(group)
{
group_category_id: group.global_group_category_id,
group_category_name: group.group_category.try(:name),
group_id: group.global_id,
uuid: group.uuid,
group_name: group.name,
context_type: group.context_type,
context_id: group.global_context_id,
account_id: group.global_account_id,
workflow_state: group.workflow_state,
max_membership: group.max_membership
}
end
def self.group_created(group)
post_event_stringified('group_created', get_group_data(group))
end
def self.group_updated(group)
post_event_stringified('group_updated', get_group_data(group))
end
def self.get_assignment_data(assignment)
event = {
assignment_id: assignment.global_id,
context_id: assignment.global_context_id,
context_uuid: assignment.context.uuid,
context_type: assignment.context_type,
assignment_group_id: assignment.global_assignment_group_id,
workflow_state: assignment.workflow_state,
title: LiveEvents.truncate(assignment.title),
description: LiveEvents.truncate(assignment.description),
due_at: assignment.due_at,
unlock_at: assignment.unlock_at,
lock_at: assignment.lock_at,
updated_at: assignment.updated_at,
points_possible: assignment.points_possible,
lti_assignment_id: assignment.lti_context_id,
lti_assignment_description: assignment.description,
lti_resource_link_id: assignment.lti_resource_link_id,
lti_resource_link_id_duplicated_from: assignment.duplicate_of&.lti_resource_link_id,
submission_types: assignment.submission_types
}
actl = assignment.assignment_configuration_tool_lookups.take
domain = assignment.root_account&.domain(ApplicationController.test_cluster_name)
event[:domain] = domain if domain
if actl
if (tool_proxy = Lti::ToolProxy.proxies_in_order_by_codes(
context: assignment.course,
vendor_code: actl.tool_vendor_code,
product_code: actl.tool_product_code,
resource_type_code: actl.tool_resource_type_code
).first)
event[:associated_integration_id] = tool_proxy.guid
# TEMPORARY: to switch over from the old format to guid,
# send both formats until all subscriptions have been changed
old_format = [actl.tool_vendor_code, actl.tool_product_code, tool_proxy.event_endpoint].join('_')
event[:associated_integration_ids] = [tool_proxy.guid, old_format]
end
end
event
end
def self.assignment_created(assignment)
post_event_stringified('assignment_created', get_assignment_data(assignment))
end
def self.assignment_updated(assignment)
post_event_stringified('assignment_updated', get_assignment_data(assignment))
end
def self.assignment_group_created(assignment_group)
post_event_stringified('assignment_group_created', get_assignment_group_data(assignment_group))
end
def self.assignment_group_updated(assignment_group)
post_event_stringified('assignment_group_updated', get_assignment_group_data(assignment_group))
end
def self.get_assignment_group_data(assignment_group)
{
assignment_group_id: assignment_group.id,
context_id: assignment_group.context_id,
context_type: assignment_group.context_type,
name: assignment_group.name,
position: assignment_group.position,
group_weight: assignment_group.group_weight,
sis_source_id: assignment_group.sis_source_id,
integration_data: assignment_group.integration_data,
rules: assignment_group.rules,
workflow_state: assignment_group.workflow_state
}
end
def self.assignments_bulk_updated(assignment_ids)
Assignment.where(:id => assignment_ids).each { |a| assignment_updated(a) }
end
def self.submissions_bulk_updated(submissions)
Submission.where(id: submissions).preload(:assignment).find_each { |submission| submission_updated(submission) }
end
def self.get_assignment_override_data(override)
data_hash = {
assignment_override_id: override.id,
assignment_id: override.assignment_id,
due_at: override.due_at,
all_day: override.all_day,
all_day_date: override.all_day_date,
unlock_at: override.unlock_at,
lock_at: override.lock_at,
type: override.set_type,
workflow_state: override.workflow_state,
}
case override.set_type
when 'CourseSection'
data_hash[:course_section_id] = override.set_id
when 'Group'
data_hash[:group_id] = override.set_id
end
data_hash
end
def self.assignment_override_created(override)
post_event_stringified('assignment_override_created', get_assignment_override_data(override))
end
def self.assignment_override_updated(override)
post_event_stringified('assignment_override_updated', get_assignment_override_data(override))
end
def self.get_submission_data(submission)
event = {
submission_id: submission.global_id,
assignment_id: submission.global_assignment_id,
user_id: submission.global_user_id,
submitted_at: submission.submitted_at,
lti_user_id: submission.lti_user_id,
graded_at: submission.graded_at,
updated_at: submission.updated_at,
score: submission.score,
grade: submission.grade,
submission_type: submission.submission_type,
body: LiveEvents.truncate(submission.body),
url: submission.url,
attempt: submission.attempt,
late: submission.late?,
missing: submission.missing?,
lti_assignment_id: submission.assignment.lti_context_id,
group_id: submission.group_id,
posted_at: submission.posted_at,
workflow_state: submission.workflow_state,
}
actl = submission.assignment.assignment_configuration_tool_lookups.take
if actl
if (tool_proxy = Lti::ToolProxy.proxies_in_order_by_codes(
context: submission.course,
vendor_code: actl.tool_vendor_code,
product_code: actl.tool_product_code,
resource_type_code: actl.tool_resource_type_code
).first)
event[:associated_integration_id] = tool_proxy.guid
# TEMPORARY: to switch over from the old format to guid,
# send both formats until all subscriptions have been changed
old_format = [actl.tool_vendor_code, actl.tool_product_code, tool_proxy.event_endpoint].join('_')
event[:associated_integration_ids] = [tool_proxy.guid, old_format]
end
end
event
end
def self.submission_event(event_type, submission)
post_event_stringified(event_type, get_submission_data(submission), amended_context(submission.context))
end
def self.get_attachment_data(attachment)
{
attachment_id: attachment.global_id,
user_id: attachment.global_user_id,
display_name: LiveEvents.truncate(attachment.display_name),
filename: LiveEvents.truncate(attachment.filename),
context_type: attachment.context_type,
context_id: attachment.global_context_id,
content_type: attachment.content_type,
folder_id: attachment.global_folder_id,
unlock_at: attachment.unlock_at,
lock_at: attachment.lock_at,
updated_at: attachment.updated_at
}
end
def self.submission_created(submission)
submission_event('submission_created', submission)
end
def self.submission_updated(submission)
submission_event('submission_updated', submission)
end
def self.submission_comment_created(comment)
payload = {
submission_comment_id: comment.id,
submission_id: comment.submission_id,
user_id: comment.author_id,
created_at: comment.created_at,
attachment_ids: comment.attachment_ids.blank? ? [] : comment.attachment_ids.split(','),
body: LiveEvents.truncate(comment.comment)
}
post_event_stringified('submission_comment_created', payload)
end
def self.plagiarism_resubmit(submission)
submission_event('plagiarism_resubmit', submission)
end
def self.get_user_data(user)
{
user_id: user.global_id,
uuid: user.uuid,
name: user.name,
short_name: user.short_name,
workflow_state: user.workflow_state,
created_at: user.created_at,
updated_at: user.updated_at,
user_login: user.primary_pseudonym&.unique_id,
user_sis_id: user.primary_pseudonym&.sis_user_id
}
end
def self.user_created(user)
post_event_stringified('user_created', get_user_data(user))
end
def self.user_updated(user)
post_event_stringified('user_updated', get_user_data(user))
end
def self.get_enrollment_data(enrollment)
data = {
enrollment_id: enrollment.global_id,
course_id: enrollment.global_course_id,
user_id: enrollment.global_user_id,
user_name: enrollment.user_name,
type: enrollment.type,
created_at: enrollment.created_at,
updated_at: enrollment.updated_at,
limit_privileges_to_course_section: enrollment.limit_privileges_to_course_section,
course_section_id: enrollment.global_course_section_id,
workflow_state: enrollment.workflow_state
}
data[:associated_user_id] = enrollment.global_associated_user_id if enrollment.observer?
data
end
def self.enrollment_created(enrollment)
post_event_stringified('enrollment_created', get_enrollment_data(enrollment))
end
def self.enrollment_updated(enrollment)
post_event_stringified('enrollment_updated', get_enrollment_data(enrollment))
end
def self.get_enrollment_state_data(enrollment_state)
{
enrollment_id: enrollment_state.global_enrollment_id,
state: enrollment_state.state,
state_started_at: enrollment_state.state_started_at,
state_is_current: enrollment_state.state_is_current,
state_valid_until: enrollment_state.state_valid_until,
restricted_access: enrollment_state.restricted_access,
access_is_current: enrollment_state.access_is_current
}
end
def self.enrollment_state_created(enrollment_state)
post_event_stringified('enrollment_state_created', get_enrollment_state_data(enrollment_state))
end
def self.enrollment_state_updated(enrollment_state)
post_event_stringified('enrollment_state_updated', get_enrollment_state_data(enrollment_state))
end
def self.user_account_association_created(assoc)
post_event_stringified('user_account_association_created', {
user_id: assoc.global_user_id,
account_id: assoc.global_account_id,
account_uuid: assoc.account.uuid,
created_at: assoc.created_at,
updated_at: assoc.updated_at,
is_admin: !(assoc.account.root_account.cached_all_account_users_for(assoc.user).empty?),
})
end
def self.logged_in(session, user, pseudonym)
ctx = LiveEvents.get_context || {}
ctx[:user_id] = user.global_id
ctx[:user_login] = pseudonym.unique_id
ctx[:user_account_id] = pseudonym.account.global_id
ctx[:user_sis_id] = pseudonym.sis_user_id
ctx[:session_id] = session[:session_id] if session[:session_id]
post_event_stringified('logged_in', {
redirect_url: session[:return_to]
}, ctx)
end
def self.logged_out
post_event_stringified('logged_out', {})
end
def self.quiz_submitted(submission)
# TODO: include score, for automatically graded portions?
post_event_stringified('quiz_submitted', {
submission_id: submission.global_id,
quiz_id: submission.global_quiz_id
})
end
def self.wiki_page_created(page)
post_event_stringified('wiki_page_created', {
wiki_page_id: page.global_id,
title: LiveEvents.truncate(page.title),
body: LiveEvents.truncate(page.body)
})
end
def self.wiki_page_updated(page, old_title, old_body)
payload = {
wiki_page_id: page.global_id,
title: LiveEvents.truncate(page.title),
body: LiveEvents.truncate(page.body)
}
if old_title
payload[:old_title] = LiveEvents.truncate(old_title)
end
if old_body
payload[:old_body] = LiveEvents.truncate(old_body)
end
post_event_stringified('wiki_page_updated', payload)
end
def self.wiki_page_deleted(page)
post_event_stringified('wiki_page_deleted', {
wiki_page_id: page.global_id,
title: LiveEvents.truncate(page.title)
})
end
def self.attachment_created(attachment)
post_event_stringified('attachment_created', get_attachment_data(attachment))
end
def self.attachment_updated(attachment, old_display_name)
payload = get_attachment_data(attachment)
if old_display_name
payload[:old_display_name] = LiveEvents.truncate(old_display_name)
end
post_event_stringified('attachment_updated', payload)
end
def self.attachment_deleted(attachment)
post_event_stringified('attachment_deleted', get_attachment_data(attachment))
end
def self.grade_changed(submission, old_submission = nil, old_assignment = submission.assignment)
grader_id = nil
if submission.grader_id && !submission.autograded?
grader_id = submission.global_grader_id
end
sis_pseudonym = GuardRail.activate(:secondary) do
SisPseudonym.for(submission.user, submission.assignment.context, type: :trusted, require_sis: false)
end
post_event_stringified('grade_change', {
submission_id: submission.global_id,
assignment_id: submission.global_assignment_id,
assignment_name: submission.assignment.name,
grade: submission.grade,
old_grade: old_submission.try(:grade),
score: submission.score,
old_score: old_submission.try(:score),
points_possible: submission.assignment.points_possible,
old_points_possible: old_assignment.points_possible,
grader_id: grader_id,
student_id: submission.global_user_id,
student_sis_id: sis_pseudonym&.sis_user_id,
user_id: submission.global_user_id,
grading_complete: submission.graded?,
muted: !submission.posted?
}, amended_context(submission.assignment.context))
end
def self.asset_access(asset, category, role, level, context: nil, context_membership: nil)
asset_subtype = nil
if asset.is_a?(Array)
asset_subtype = asset[0]
asset_obj = asset[1]
else
asset_obj = asset
end
enrollment_data = {}
if context_membership.is_a?(Enrollment)
enrollment_data = {
enrollment_id: context_membership.id,
section_id: context_membership.course_section_id
}
end
post_event_stringified(
'asset_accessed',
{
asset_name: asset_obj.try(:name) || asset_obj.try(:title),
asset_type: asset_obj.class.reflection_type_name,
asset_id: asset_obj.global_id,
asset_subtype: asset_subtype,
category: category,
role: role,
level: level
}.merge(LiveEvents::EventSerializerProvider.serialize(asset_obj)).merge(enrollment_data),
amended_context(context)
)
end
def self.quiz_export_complete(content_export)
payload = content_export.settings[:quizzes2]
post_event_stringified('quiz_export_complete', payload, amended_context(content_export.context))
end
def self.content_migration_completed(content_migration)
post_event_stringified(
'content_migration_completed',
content_migration_data(content_migration),
amended_context(content_migration.context)
)
end
def self.content_migration_data(content_migration)
context = content_migration.context
import_quizzes_next =
content_migration.migration_settings&.[](:import_quizzes_next) == true
payload = {
content_migration_id: content_migration.global_id,
context_id: context.global_id,
context_type: context.class.to_s,
lti_context_id: context.lti_context_id,
context_uuid: context.uuid,
import_quizzes_next: import_quizzes_next,
source_course_lti_id: content_migration.source_course&.lti_context_id,
destination_course_lti_id: context.lti_context_id,
migration_type: content_migration.migration_type
}
if context.respond_to?(:root_account)
payload[:domain] = context.root_account&.domain(ApplicationController.test_cluster_name)
end
payload
end
def self.course_section_created(section)
post_event_stringified('course_section_created', get_course_section_data(section))
end
def self.course_section_updated(section)
post_event_stringified('course_section_updated', get_course_section_data(section))
end
def self.quizzes_next_quiz_duplicated(payload)
post_event_stringified('quizzes_next_quiz_duplicated', payload)
end
def self.get_course_section_data(section)
{
course_section_id: section.id,
sis_source_id: section.sis_source_id,
sis_batch_id: section.sis_batch_id,
course_id: section.course_id,
root_account_id: section.root_account_id,
enrollment_term_id: section.enrollment_term_id,
name: section.name,
default_section: section.default_section,
accepting_enrollments: section.accepting_enrollments,
can_manually_enroll: section.can_manually_enroll,
start_at: section.start_at,
end_at: section.end_at,
workflow_state: section.workflow_state,
restrict_enrollments_to_section_dates: section.restrict_enrollments_to_section_dates,
nonxlist_course_id: section.nonxlist_course_id,
stuck_sis_fields: section.stuck_sis_fields,
integration_id: section.integration_id
}
end
def self.module_created(context_module)
post_event_stringified('module_created', get_context_module_data(context_module))
end
def self.module_updated(context_module)
post_event_stringified('module_updated', get_context_module_data(context_module))
end
def self.get_context_module_data(context_module)
{
module_id: context_module.id,
context_id: context_module.context_id,
context_type: context_module.context_type,
name: context_module.name,
position: context_module.position,
workflow_state: context_module.workflow_state
}
end
def self.module_item_created(context_module_item)
post_event_stringified('module_item_created', get_context_module_item_data(context_module_item))
end
def self.module_item_updated(context_module_item)
post_event_stringified('module_item_updated', get_context_module_item_data(context_module_item))
end
def self.get_context_module_item_data(context_module_item)
{
module_item_id: context_module_item.id,
module_id: context_module_item.context_module_id,
context_id: context_module_item.context_id,
context_type: context_module_item.context_type,
position: context_module_item.position,
workflow_state: context_module_item.workflow_state
}
end
def self.course_completed(context_module_progression)
post_event_stringified('course_completed',
get_course_completed_data(
context_module_progression.context_module.course,
context_module_progression.user
))
end
def self.course_progress(context_module_progression)
post_event_stringified('course_progress', get_course_completed_data(context_module_progression.context_module.course, context_module_progression.user))
end
def self.get_course_completed_data(course, user)
{
progress: CourseProgress.new(course, user, read_only: true).to_json,
user: user.slice(%i[id name email]),
course: course.slice(%i[id name account_id sis_source_id])
}
end
def self.get_learning_outcome_result_data(result)
{
learning_outcome_id: result.learning_outcome_id,
mastery: result.mastery,
score: result.score,
created_at: result.created_at,
attempt: result.attempt,
possible: result.possible,
original_score: result.original_score,
original_possible: result.original_possible,
original_mastery: result.original_mastery,
assessed_at: result.assessed_at,
title: result.title,
percent: result.percent,
workflow_state: result.workflow_state
}
end
def self.learning_outcome_result_updated(result)
post_event_stringified('learning_outcome_result_updated', get_learning_outcome_result_data(result).merge(updated_at: result.updated_at))
end
def self.learning_outcome_result_created(result)
post_event_stringified('learning_outcome_result_created', get_learning_outcome_result_data(result))
end
def self.get_learning_outcome_data(outcome)
{
learning_outcome_id: outcome.id,
context_type: outcome.context_type,
context_id: outcome.context_id,
display_name: outcome.display_name,
short_description: outcome.short_description,
description: outcome.description,
vendor_guid: outcome.vendor_guid,
calculation_method: outcome.calculation_method,
calculation_int: outcome.calculation_int,
rubric_criterion: outcome.rubric_criterion,
title: outcome.title,
workflow_state: outcome.workflow_state
}
end
def self.learning_outcome_updated(outcome)
post_event_stringified('learning_outcome_updated', get_learning_outcome_data(outcome).merge(updated_at: outcome.updated_at))
end
def self.learning_outcome_created(outcome)
post_event_stringified('learning_outcome_created', get_learning_outcome_data(outcome))
end
def self.get_learning_outcome_group_data(group)
{
learning_outcome_group_id: group.id,
context_id: group.context_id,
context_type: group.context_type,
title: group.title,
description: group.description,
vendor_guid: group.vendor_guid,
parent_outcome_group_id: group.learning_outcome_group_id,
workflow_state: group.workflow_state
}
end
def self.learning_outcome_group_updated(group)
post_event_stringified('learning_outcome_group_updated', get_learning_outcome_group_data(group).merge(updated_at: group.updated_at))
end
def self.learning_outcome_group_created(group)
post_event_stringified('learning_outcome_group_created', get_learning_outcome_group_data(group))
end
def self.get_learning_outcome_link_data(link)
{
learning_outcome_link_id: link.id,
learning_outcome_id: link.content_id,
learning_outcome_group_id: link.associated_asset_id,
context_id: link.context_id,
context_type: link.context_type,
workflow_state: link.workflow_state
}
end
def self.learning_outcome_link_created(link)
post_event_stringified('learning_outcome_link_created', get_learning_outcome_link_data(link))
end
def self.learning_outcome_link_updated(link)
post_event_stringified('learning_outcome_link_updated', get_learning_outcome_link_data(link).merge(updated_at: link.updated_at))
end
def self.grade_override(score, old_score, enrollment, course)
return unless score.course_score && score.override_score != old_score
data = {
score_id: score.id,
enrollment_id: score.enrollment_id,
user_id: enrollment.user_id,
course_id: enrollment.course_id,
grading_period_id: score.grading_period_id,
override_score: score.override_score,
old_override_score: old_score,
updated_at: score.updated_at,
}
post_event_stringified('grade_override', data, amended_context(course))
end
def self.course_grade_change(score, old_score_values, enrollment)
data = {
user_id: enrollment.user_id,
course_id: enrollment.course_id,
workflow_state: score.workflow_state,
created_at: score.created_at,
updated_at: score.updated_at,
current_score: score.current_score,
old_current_score: old_score_values[:current_score],
final_score: score.final_score,
old_final_score: old_score_values[:final_score],
unposted_current_score: score.unposted_current_score,
old_unposted_current_score: old_score_values[:unposted_current_score],
unposted_final_score: score.unposted_final_score,
old_unposted_final_score: old_score_values[:unposted_final_score]
}
post_event_stringified('course_grade_change', data, amended_context(score.course))
end
def self.sis_batch_payload(batch)
{
sis_batch_id: batch.id,
account_id: batch.account_id,
workflow_state: batch.workflow_state
}
end
def self.sis_batch_created(batch)
post_event_stringified('sis_batch_created', sis_batch_payload(batch))
end
def self.sis_batch_updated(batch)
post_event_stringified('sis_batch_updated', sis_batch_payload(batch))
end
def self.outcome_proficiency_created(proficiency)
post_event_stringified('outcome_proficiency_created', get_outcome_proficiency_data(proficiency))
end
def self.outcome_proficiency_updated(proficiency)
post_event_stringified('outcome_proficiency_updated', get_outcome_proficiency_data(proficiency).merge(updated_at: proficiency.updated_at))
end
def self.get_outcome_proficiency_data(proficiency)
ratings = proficiency.outcome_proficiency_ratings.map do |rating|
get_outcome_proficiency_rating_data(rating)
end
{
outcome_proficiency_id: proficiency.id,
context_type: proficiency.context_type,
context_id: proficiency.context_id,
workflow_state: proficiency.workflow_state,
outcome_proficiency_ratings: ratings
}
end
def self.get_outcome_proficiency_rating_data(rating)
{
outcome_proficiency_rating_id: rating.id,
description: rating.description,
points: rating.points,
mastery: rating.mastery,
color: rating.color,
workflow_state: rating.workflow_state
}
end
def self.outcome_calculation_method_created(method)
post_event_stringified('outcome_calculation_method_created', get_outcome_calculation_method_data(method))
end
def self.outcome_calculation_method_updated(method)
post_event_stringified('outcome_calculation_method_updated', get_outcome_calculation_method_data(method).merge(updated_at: method.updated_at))
end
def self.get_outcome_calculation_method_data(method)
{
outcome_calculation_method_id: method.id,
context_type: method.context_type,
context_id: method.context_id,
workflow_state: method.workflow_state,
calculation_method: method.calculation_method,
calculation_int: method.calculation_int
}
end
def self.outcome_friendly_description_created(description)
post_event_stringified('outcome_friendly_description_created', get_outcome_friendly_description_data(description))
end
def self.outcome_friendly_description_updated(description)
post_event_stringified('outcome_friendly_description_updated', get_outcome_friendly_description_data(description).merge(updated_at: description.updated_at))
end
def self.get_outcome_friendly_description_data(description)
{
outcome_friendly_description_id: description.id,
context_type: description.context_type,
context_id: description.context_id,
description: description.description,
workflow_state: description.workflow_state,
learning_outcome_id: description.learning_outcome_id,
root_account_id: description.root_account_id
}
end
end