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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,12 @@ Templates for required seed files are located in the [seed_templates](seed_templ

`oneroster:active_school_year`: The school-year on which to build OneRoster files. This should be rotated at year-rollover time, when incoming data from the school year that's about to begin has settled enough to support rostering.

`oneroster:include_parents`: Boolean, whether or not to include parents in `users`. If true, users with role `parent` will include the `sourcedIds` of students to which they're associated in `agentSourcedIds`; likewise users with role `student` will include the `sourcedIds` of parents to which they're associated in `agentSourcedIds`. (Default is false.)

`oneroster:student_email_type`: The email_type that will be preferred for student users.
`oneroster:parent_email_type`: The email_type that will be preferred for parent users.

`oneroster:parent_telephone_type`: The phone_number_type that will be preferred for parent users.

`oneroster:demographic_extensions`: Extensions to add to the demographic table. These are
key-value pairs composed of a column name from `dim_student` and the desired column name in
Expand Down
31 changes: 31 additions & 0 deletions models/oneroster_1_1/or1_1__int_student_parent_bridge.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{#
This "bridge" table is used by both int_users_parent and int_users_student
to link students and parents (via the OneRoster agentSourcedIds).
#}
{{
config(
materialized = 'ephemeral'
)
}}

with dim_parent as (
select * exclude tenant_code from {{ ref('dim_parent') }}
where school_year = {{ var('oneroster:active_school_year')}}
),
dim_student as (
select * exclude tenant_code from {{ ref('dim_student') }}
),
student_parent as (
select * from {{ ref('fct_student_parent_association') }}
where school_year = {{ var('oneroster:active_school_year')}}
)
select
student_parent.k_student,
{{ gen_sourced_id('student') }} as student_sourced_id,
student_parent.k_parent,
{{ gen_sourced_id('parent') }} as parent_sourced_id
from dim_student
join student_parent
on student_parent.k_student = dim_student.k_student
join dim_parent
on dim_parent.k_parent = student_parent.k_parent
123 changes: 123 additions & 0 deletions models/oneroster_1_1/or1_1__int_users_parent.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
{{
config(
materialized = 'ephemeral',
)
}}

with dim_parent as (
select * from {{ ref('dim_parent') }}
where school_year = {{ var('oneroster:active_school_year')}}
),
student_school as (
select * exclude tenant_code from {{ ref('fct_student_school_association') }}
where school_year = {{ var('oneroster:active_school_year')}}
),
dim_school as (
select * exclude tenant_code from {{ ref('dim_school') }}
),
parent_email as (
{{
edu_wh.row_pluck(ref('stg_ef3__contacts__emails'),
key='k_contact',
column='email_type',
preferred=var('oneroster:parent_email_type', 'Home/Personal'),
where='(do_not_publish is null or not do_not_publish)')
}}
),
parent_telephone as (
{{
edu_wh.row_pluck(ref('stg_ef3__contacts__telephones'),
key='k_contact',
column='phone_number_type',
preferred=var('oneroster:parent_telephone_type', 'Mobile'),
Comment thread
tomreitz marked this conversation as resolved.
where='(do_not_publish is null or not do_not_publish)')
}}
),

parent_orgs as (
Comment thread
tomreitz marked this conversation as resolved.
select
dim_parent.k_parent,
dim_school.k_lea,
dim_school.k_school,
dim_school.school_id,
{{ gen_sourced_id('school') }} as sourced_id,
student_school.is_primary_school,
student_school.entry_date,
dim_parent.tenant_code
from dim_parent
join {{ ref('or1_1__int_student_parent_bridge') }} student_parent_bridge
on dim_parent.k_parent = student_parent_bridge.k_parent
join student_school
on student_school.k_student = student_parent_bridge.k_student
join dim_school
on student_school.k_school = dim_school.k_school
),
parent_orgs_agg as (
select
k_parent,
listagg(distinct sourced_id, ',') as orgs
from parent_orgs
group by all
),

parent_students as (
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OneRoster has users.agentSourcedIds about which the docs say

Humans may have relationships with other humans. For example, a student may have parents. The "agents" attribute allows for relationships between humans to be expressed. Note that these are typically from the point of view of the student - so a student will link to its parents (via the agent attribute). The reverse view MUST also be modeled, so for example, a user of role "parent" MUST have agents that are of type "student".

This CTE constructs the array of sourcedIds of students for each parent; a similar CTE was added to int_user_student to construct the array of sourcedIds of parents for each student.

select
dim_parent.k_parent,
student_sourced_id as sourced_id,
dim_parent.tenant_code
from dim_parent
join {{ ref('or1_1__int_student_parent_bridge') }} student_parent_bridge
on dim_parent.k_parent = student_parent_bridge.k_parent
),
parent_students_agg as (
select
k_parent,
listagg(distinct sourced_id, ',') as students
from parent_students
group by all
),

parent_keys as (
select
k_parent,
{{ gen_sourced_id('parent') }} as sourced_id,
{{ gen_natural_key('parent') }} as natural_key
from dim_parent
),
formatted as (
select
parent_keys.sourced_id as "sourcedId",
null::string as "status",
null::date as "dateLastModified",
true as "enabledUser",
parent_orgs_agg.orgs as "orgSourcedIds",
'parent' as "role",
parent_email.email_address as "username",
null::string as "userIds",
dim_parent.first_name as "givenName",
dim_parent.last_name as "familyName",
dim_parent.middle_name as "middleName",
dim_parent.parent_unique_id as "identifier",
parent_email.email_address as "email",
null::string as "sms",
parent_telephone.phone_number as "phone",
Comment thread
tomreitz marked this conversation as resolved.
parent_students_agg.students as "agentSourcedIds",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I kept agentSourcedIds here because that's what the staff and student users use, but I think according to the OneRoster 1.1 spec it should be just agents?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤨 i truly don't know

null::string as "grades",
null::string as "password",
parent_keys.natural_key as "metadata.edu.natural_key",
null::string as "metadata.edu.staff_classfication",
null::string as "metadata.edu.primary_school",
dim_parent.tenant_code
from dim_parent
join parent_keys
on dim_parent.k_parent = parent_keys.k_parent
left join parent_orgs_agg
on dim_parent.k_parent = parent_orgs_agg.k_parent
left join parent_students_agg
on dim_parent.k_parent = parent_students_agg.k_parent
left join parent_email
on dim_parent.k_parent = parent_email.k_contact
left join parent_telephone
on dim_parent.k_parent = parent_telephone.k_contact
)
select * from formatted
29 changes: 29 additions & 0 deletions models/oneroster_1_1/or1_1__int_users_student.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ student_school as (
select * from {{ ref('fct_student_school_association') }}
where school_year = {{ var('oneroster:active_school_year')}}
),

dim_school as (
select * exclude tenant_code from {{ ref('dim_school') }}
),
Expand Down Expand Up @@ -61,6 +62,26 @@ student_orgs_agg as (
from student_orgs
group by all
),

{% if var('oneroster:include_parents', False) %}
student_parents as (
select
dim_student.k_student,
parent_sourced_id as sourced_id,
dim_student.tenant_code
from dim_student
join {{ ref('or1_1__int_student_parent_bridge') }} student_parent_bridge
on dim_student.k_student = student_parent_bridge.k_student
),
student_parents_agg as (
select
k_student,
listagg(distinct sourced_id, ',') as parents
from student_parents
group by all
),
{% endif %}

student_keys as (
select
k_student,
Expand All @@ -85,7 +106,11 @@ formatted as (
student_email.email_address as "email",
null::string as "sms",
null::string as "phone",
{% if var('oneroster:include_parents', False) %}
student_parents_agg.parents as "agentSourcedIds",
{% else %}
null::string as "agentSourcedIds",
{% endif%}
grade_level_xwalk.oneroster_grade_level as "grades",
null::string as "password",
student_keys.natural_key as "metadata.edu.natural_key",
Expand All @@ -97,6 +122,10 @@ formatted as (
on dim_student.k_student = student_keys.k_student
left join student_orgs_agg
on dim_student.k_student = student_orgs_agg.k_student
{% if var('oneroster:include_parents', False) %}
left join student_parents_agg
on dim_student.k_student = student_parents_agg.k_student
{% endif %}
left join user_ids
on dim_student.k_student = user_ids.k_student
left join student_email
Expand Down
2 changes: 1 addition & 1 deletion models/oneroster_1_1/or1_1__users.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ union all
select * from {{ ref('or1_1__int_users_staff') }}
{% if var('oneroster:include_parents', False) %}
union all
select * from {{ ref('or1_1__int_users_parents') }}
select * from {{ ref('or1_1__int_users_parent') }}
Comment thread
rlittle08 marked this conversation as resolved.
{% endif %}