diff --git a/course/models.py b/course/models.py index f1f2fc873a3cf1a77da530174778b22abb5b2b5f..0a3dfe5462a54056e720172f8bdfe7ee0e6878e0 100644 --- a/course/models.py +++ b/course/models.py @@ -63,6 +63,7 @@ from course.page.base import AnswerFeedback if False: from typing import List, Dict, Any, Optional, Text, Iterable, Tuple, FrozenSet # noqa from course.content import FlowDesc # noqa + import datetime # noqa # }}} @@ -819,6 +820,7 @@ class FlowSession(models.Model): return assemble_answer_visits(self) def last_activity(self): + # type: () -> Optional[datetime.datetime] for visit in (FlowPageVisit.objects .filter( flow_session=self, diff --git a/course/utils.py b/course/utils.py index 944fbcabbf8cc67e9e640836c522550b2d99f8e4..ffbee615d24e6df09fac72fbcd51266b399e3bad 100644 --- a/course/utils.py +++ b/course/utils.py @@ -493,9 +493,25 @@ def get_session_grading_rule( if hasattr(rule, "if_completed_before"): ds = parse_date_spec(session.course, rule.if_completed_before) - if session.in_progress and now_datetime > ds: - continue - if not session.in_progress and session.completion_time > ds: + + use_last_activity_as_completion_time = False + if hasattr(rule, "use_last_activity_as_completion_time"): + use_last_activity_as_completion_time = \ + rule.use_last_activity_as_completion_time + + if use_last_activity_as_completion_time: + last_activity = session.last_activity() + if last_activity is not None: + completion_time = last_activity + else: + completion_time = now_datetime + else: + if session.in_progress: + completion_time = now_datetime + else: + completion_time = session.completion_time + + if completion_time > ds: continue due = parse_date_spec(session.course, getattr(rule, "due", None)) diff --git a/doc/flow.rst b/doc/flow.rst index b1cf6ba3c5544197976ca3c611467163a6cc0af3..a9886a90c51097a7c86e004e1372e061bcfaf55c 100644 --- a/doc/flow.rst +++ b/doc/flow.rst @@ -510,6 +510,12 @@ Determining how final (overall) grades of flows are computed (Optional) A :ref:`datespec `. Rule applies if the session was completed before this time. + When evaluating this condition for in-progress sessions, the current time, + or, if :attr:`use_last_activity_as_completion_time` is set, the time of the + last activity is used. + + Since September 2017, this respects :attr:`use_last_activity_as_completion_time`. + .. rubric:: Rules specified .. attribute:: credit_percent