Skip to content

Commit

Permalink
Model definition for LMSUserAssignmentMembership
Browse files Browse the repository at this point in the history
This is mostly a duplicate of AssignmentMembership but that table has a
composed primary key that makes changes to the schema more challenging.

The new table continues the same line of work as LMSCourseMembership and
similar tables.

It also includes the `lti_v11_lis_result_sourcedid` column to store the
grading ID of the user in one assignment to enable participation grading
in LTI1.1
  • Loading branch information
marcospri committed Oct 8, 2024
1 parent 8c962b8 commit 034cefc
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 20 deletions.
5 changes: 4 additions & 1 deletion lms/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
from lms.models.application_instance import ApplicationInstance, ApplicationSettings
from lms.models.assignment import Assignment, AutoGradingConfig
from lms.models.assignment_grouping import AssignmentGrouping
from lms.models.assignment_membership import AssignmentMembership
from lms.models.assignment_membership import (
AssignmentMembership,
LMSUserAssignmentMembership,
)
from lms.models.course_groups_exported_from_h import CourseGroupsExportedFromH
from lms.models.dashboard_admin import DashboardAdmin
from lms.models.event import Event, EventData, EventType, EventUser
Expand Down
60 changes: 42 additions & 18 deletions lms/models/assignment_membership.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sqlalchemy as sa
from sqlalchemy import ForeignKey, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship

from lms.db import Base
from lms.models._mixins import CreatedUpdatedMixin
Expand All @@ -9,29 +10,52 @@ class AssignmentMembership(CreatedUpdatedMixin, Base):

__tablename__ = "assignment_membership"

assignment_id = sa.Column(
sa.Integer(),
sa.ForeignKey("assignment.id", ondelete="cascade"),
primary_key=True,
index=True,
assignment_id: Mapped[int] = mapped_column(
ForeignKey("assignment.id", ondelete="cascade"), primary_key=True, index=True
)
assignment = sa.orm.relationship("Assignment", foreign_keys=[assignment_id])
assignment = relationship("Assignment", foreign_keys=[assignment_id])
"""The assignment the user is a member of."""

user_id = sa.Column(
sa.Integer(),
sa.ForeignKey("user.id", ondelete="cascade"),
primary_key=True,
index=True,
user_id: Mapped[int] = mapped_column(
ForeignKey("user.id", ondelete="cascade"), primary_key=True, index=True
)
user = sa.orm.relationship("User", foreign_keys=[user_id])
user = relationship("User", foreign_keys=[user_id])
"""The user who is a member."""

lti_role_id = sa.Column(
sa.Integer(),
sa.ForeignKey("lti_role.id", ondelete="cascade"),
primary_key=True,
lti_role_id: Mapped[int] = mapped_column(
ForeignKey("lti_role.id", ondelete="cascade"), primary_key=True, index=True
)
lti_role = relationship("LTIRole", foreign_keys=[lti_role_id])
"""What role the user plays in the assignment."""


class LMSUserAssignmentMembership(CreatedUpdatedMixin, Base):
"""Record of LMSUser that have launched one particular assignment.
One row for each assignment, user and role.
"""

__tablename__ = "lms_user_assignment_membership"
__table_args__ = (UniqueConstraint("assignment_id", "lms_user_id", "lti_role_id"),)

id: Mapped[int] = mapped_column(autoincrement=True, primary_key=True)

assignment_id: Mapped[int] = mapped_column(
ForeignKey("assignment.id", ondelete="cascade"), index=True
)
assignment = relationship("Assignment", foreign_keys=[assignment_id])

lms_user_id: Mapped[int] = mapped_column(
ForeignKey("lms_user.id", ondelete="cascade"), index=True
)
lms_user = relationship("LMSUser", foreign_keys=[lms_user_id])

lti_role_id: Mapped[int] = mapped_column(
ForeignKey("lti_role.id", ondelete="cascade"),
index=True,
)
lti_role = sa.orm.relationship("LTIRole", foreign_keys=[lti_role_id])
lti_role = relationship("LTIRole", foreign_keys=[lti_role_id])
"""What role the user plays in the assignment."""

lti_v11_lis_result_sourcedid: Mapped[str | None] = mapped_column()
"""LTI's lis_result_sourcedid, the relevant ID of one user in one assigment for the LTI1.1 grading API."""
5 changes: 4 additions & 1 deletion tests/factories/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from tests.factories.application_instance import ApplicationInstance
from tests.factories.assignment import Assignment
from tests.factories.assignment_grouping import AssignmentGrouping
from tests.factories.assignment_membership import AssignmentMembership
from tests.factories.assignment_membership import (
AssignmentMembership,
LMSUserAssignmentMembership,
)
from tests.factories.attributes import (
ACCESS_TOKEN,
H_DISPLAY_NAME,
Expand Down
4 changes: 4 additions & 0 deletions tests/factories/assignment_membership.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
AssignmentMembership = make_factory(
models.AssignmentMembership, FACTORY_CLASS=SQLAlchemyModelFactory
)

LMSUserAssignmentMembership = make_factory(
models.LMSUserAssignmentMembership, FACTORY_CLASS=SQLAlchemyModelFactory
)

0 comments on commit 034cefc

Please sign in to comment.