Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/ol_dbt/models/reporting/_reporting__models.yml
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,60 @@ models:
column_list: ["user_email", "platform", "courserun_readable_id", "course_title",
"section_title", "section_block_index"]

- name: page_engagement_views_report
description: Page engagement report showing user activity at the unit, subsection,
and section level across course runs. Joins page engagement facts with course
content hierarchy and user information.
columns:
- name: user_email
description: string, email address of the user. May be null when user_fk is null.
- name: full_name
description: string, full name of the user
- name: platform
description: string, name of the platform
tests:
- not_null
- name: courserun_readable_id
description: string, unique identifier for the course run formatted as course-v1:{org}+{course
code}+{run_tag}
tests:
- not_null
- name: block_fk
description: string, foreign key to dim_course_content for the vertical (unit)
block
tests:
- not_null
- name: openedx_user_id
description: int, the user's numeric ID in the OpenedX platform
tests:
- not_null
- name: num_of_views
description: int, number of times the user viewed this page unit
tests:
- not_null
- name: unit_title
description: string, title of the vertical (unit) block within the course. May
be null if block_fk does not match dim_course_content.
- name: subsection_title
description: string, title of the sequential (subsection) block within the course.
May be null if sequential_block_fk does not match or is null.
- name: subsection_block_index
description: int, sequence number giving the order in which this subsection appears
within the section. May be null if sequential_block_fk does not match or is
null.
- name: section_title
description: string, title of the chapter (section) block within the course. May
be null if chapter_block_fk does not match or is null.
- name: section_block_index
description: int, sequence number giving the order in which this section appears
within the course. May be null if chapter_block_fk does not match or is null.
- name: course_title
description: string, title of the course run. May be null if courserun_readable_id
does not match.
tests:
- dbt_expectations.expect_compound_columns_to_be_unique:
column_list: ["platform", "openedx_user_id", "courserun_readable_id", "block_fk"]

- name: program_enrollment_with_user_report
description: Program enrollment report enriched with user demographic data and course
completion details. Extends marts__combined_program_enrollment_detail with user
Expand Down
66 changes: 66 additions & 0 deletions src/ol_dbt/models/reporting/page_engagement_views_report.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
with page_engagement as (
select * from {{ ref('afact_course_page_engagement') }}
)

, dim_user as (
select * from {{ ref('dim_user') }}
)

, course_runs as (
select
course_title
, courserun_readable_id
from {{ ref('int__combined__course_runs') }}
group by course_title, courserun_readable_id
)
Comment thread
sentry[bot] marked this conversation as resolved.

, unit_blocks as (
select * from {{ ref('dim_course_content') }}
where block_category = 'vertical'
and is_latest = true
)

, subsection_blocks as (
select * from {{ ref('dim_course_content') }}
where is_latest = true
and block_category = 'sequential'
)

, section_blocks as (
select * from {{ ref('dim_course_content') }}
where is_latest = true
Comment thread
quazi-h marked this conversation as resolved.
and block_category = 'chapter'
)
Comment on lines +23 to +33
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subsection_blocks and section_blocks CTEs are redundant - they both select all columns from dim_course_content with only the is_latest = true filter. This creates unnecessary code duplication and could lead to maintenance issues if filters need to be updated.

Consider consolidating these into a single CTE (e.g., course_content_blocks) and reusing it for both joins, or selecting only the specific columns needed for each join to make the purpose clearer.

Copilot uses AI. Check for mistakes.

select
dim_user.email as user_email
, dim_user.full_name
, page_engagement.platform
, page_engagement.courserun_readable_id
, page_engagement.block_fk
, page_engagement.openedx_user_id
, max(page_engagement.num_of_views) as num_of_views
, max(unit_blocks.block_title) as unit_title
, max(subsection_blocks.block_title) as subsection_title
, max(subsection_blocks.block_index) as subsection_block_index
, max(section_blocks.block_title) as section_title
, max(section_blocks.block_index) as section_block_index
, max(course_runs.course_title) as course_title
from page_engagement
left join unit_blocks
on page_engagement.block_fk = unit_blocks.block_id
left join subsection_blocks
on page_engagement.sequential_block_fk = subsection_blocks.block_id
left join section_blocks
Comment thread
sentry[bot] marked this conversation as resolved.
on page_engagement.chapter_block_fk = section_blocks.block_id
left join dim_user
on page_engagement.user_fk= dim_user.user_pk
left join course_runs
on page_engagement.courserun_readable_id = course_runs.courserun_readable_id
group by
dim_user.email
, dim_user.full_name
, page_engagement.platform
, page_engagement.courserun_readable_id
, page_engagement.block_fk
Comment thread
sentry[bot] marked this conversation as resolved.
, page_engagement.openedx_user_id