From bdddb008d5d398ed67f11fdc4fa7c0653b71d653 Mon Sep 17 00:00:00 2001 From: Marcos Prieto Date: Mon, 16 Sep 2024 14:51:43 +0200 Subject: [PATCH] Model for GradingSync --- lms/models/__init__.py | 1 + lms/models/grading_sync.py | 60 +++++++++++++++++++++++++++++++++ tests/factories/__init__.py | 1 + tests/factories/grading_sync.py | 19 +++++++++++ 4 files changed, 81 insertions(+) create mode 100644 lms/models/grading_sync.py create mode 100644 tests/factories/grading_sync.py diff --git a/lms/models/__init__.py b/lms/models/__init__.py index 04996cd473..80e10d59ae 100644 --- a/lms/models/__init__.py +++ b/lms/models/__init__.py @@ -9,6 +9,7 @@ from lms.models.exceptions import ReusedConsumerKey from lms.models.file import File from lms.models.grading_info import GradingInfo +from lms.models.grading_sync import GradingSync, GradingSyncGrade from lms.models.group_info import GroupInfo from lms.models.grouping import ( BlackboardGroup, diff --git a/lms/models/grading_sync.py b/lms/models/grading_sync.py new file mode 100644 index 0000000000..7b8e7aecaf --- /dev/null +++ b/lms/models/grading_sync.py @@ -0,0 +1,60 @@ +from enum import StrEnum +from typing import TYPE_CHECKING + +from sqlalchemy import ForeignKey, text +from sqlalchemy.dialects.postgresql import JSONB +from sqlalchemy.orm import Mapped, mapped_column, relationship + +from lms.db import Base, varchar_enum +from lms.models import Assignment +from lms.models._mixins import CreatedUpdatedMixin + +if TYPE_CHECKING: + from lms.models import LMSUser + + +class AutoGradingSyncStatus(StrEnum): + SCHEDULED = "scheduled" + IN_PROGRESS = "in_progress" + FINISHED = "finished" + FAILED = "failed" + + +class GradingSync(CreatedUpdatedMixin, Base): + __tablename__ = "grading_sync" + + id: Mapped[int] = mapped_column(autoincrement=True, primary_key=True) + + assignment_id: Mapped[int] = mapped_column(ForeignKey("assignment.id"), index=True) + assignment: Mapped[Assignment] = relationship() + + status: Mapped[str | None] = varchar_enum(AutoGradingSyncStatus) + + created_by_id: Mapped[int] = mapped_column(ForeignKey("lms_user.id")) + created_by: Mapped["LMSUser"] = relationship() + """Who created this grade sync.""" + + +class GradingSyncGrade(CreatedUpdatedMixin, Base): + __tablename__ = "grading_sync_grade" + + id: Mapped[int] = mapped_column(autoincrement=True, primary_key=True) + + grading_sync_id: Mapped[int] = mapped_column( + ForeignKey("grading_sync.id"), index=True + ) + grading_sync: Mapped[GradingSync] = relationship(backref="grades") + + lms_user_id: Mapped[int] = mapped_column(ForeignKey("lms_user.id"), index=True) + lms_user: Mapped["LMSUser"] = relationship() + """Who this grade belongs to""" + + grade: Mapped[float] = mapped_column() + + error_details: Mapped[JSONB] = mapped_column( + JSONB(), server_default=text("'{}'::jsonb"), nullable=False + ) + """Any extra information about potential errors while syncing this grade to the LMS""" + + success: Mapped[bool | None] = mapped_column() + """Whether or not this grade has been synced to the LMS""" diff --git a/tests/factories/__init__.py b/tests/factories/__init__.py index b9174bff64..1efdafdd31 100644 --- a/tests/factories/__init__.py +++ b/tests/factories/__init__.py @@ -22,6 +22,7 @@ from tests.factories.event import Event from tests.factories.file import File from tests.factories.grading_info import GradingInfo +from tests.factories.grading_sync import GradingSync, GradingSyncGrade from tests.factories.group_info import GroupInfo from tests.factories.grouping import BlackboardGroup, CanvasGroup, CanvasSection, Course from tests.factories.grouping_membership import GroupingMembership diff --git a/tests/factories/grading_sync.py b/tests/factories/grading_sync.py new file mode 100644 index 0000000000..c3e0ba907b --- /dev/null +++ b/tests/factories/grading_sync.py @@ -0,0 +1,19 @@ +from factory import Faker, SubFactory, make_factory +from factory.alchemy import SQLAlchemyModelFactory + +from lms import models +from lms.models.grading_sync import AutoGradingSyncStatus +from tests.factories.lms_user import LMSUser + + +class GradingSync(SQLAlchemyModelFactory): + class Meta: + model = models.GradingSync + + created_by = SubFactory(LMSUser) + status = Faker("random_element", elements=list(AutoGradingSyncStatus)) + + +GradingSyncGrade = make_factory( + models.GradingSyncGrade, FACTORY_CLASS=SQLAlchemyModelFactory +)