Skip to content

zimka/master -- initial #2

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
87b38c4
Course Shift Models
zimka Sep 5, 2017
c21a02c
Models improvements
zimka Sep 7, 2017
6852a6f
Basic tests passed
zimka Sep 11, 2017
9a6b110
README added
zimka Sep 11, 2017
520ff08
Model update, tests for settings
zimka Sep 12, 2017
f8cf126
Added manager for operations on user
zimka Sep 12, 2017
7c9e565
Manager update and manager tests
zimka Sep 13, 2017
f137170
Review fixes
zimka Sep 13, 2017
dcb6a53
Logging, formating and small fix
zimka Sep 14, 2017
a5bcd51
Manager and tests refactoring
zimka Sep 15, 2017
8591f0a
Manager and tests refactoring 2
zimka Sep 17, 2017
cbfae55
Manager and test refactoring 3
zimka Sep 19, 2017
22b261a
Field Override Provider added
zimka Sep 20, 2017
b940d4f
Settings serializer and api added
zimka Sep 21, 2017
a008c6f
Added settings edit view
zimka Sep 25, 2017
006febb
Added list and detail api for course shifts
zimka Sep 26, 2017
89e9b5b
Added shift edit view; GET part
zimka Sep 27, 2017
83f872d
Added shift edit view; PATCH, POST and DELETE parts
zimka Sep 28, 2017
2b80f45
Added user api and view
zimka Sep 28, 2017
7b8d665
UI fixes
zimka Sep 29, 2017
d24cb92
Edx files that are modified to make feature work
zimka Sep 29, 2017
99b441c
Added student shift enrollment at course enrollment
zimka Sep 29, 2017
49859b1
Fix error messages disappear after view re-rendering
zimka Oct 2, 2017
d7f2a9b
README update, shift start_date change bug fix
zimka Oct 2, 2017
b5dfcd8
Merge pull request #3 from zimka/develop
martynovp Oct 3, 2017
9ecab23
Create setup.py
martynovp Oct 3, 2017
e9403e6
Move app into course_shifts
martynovp Oct 3, 2017
a634269
Code style fixes
martynovp Oct 3, 2017
1da7990
Migrations
martynovp Oct 3, 2017
0f5ce6e
Instructor dahboard templates
martynovp Oct 3, 2017
2fff757
Add course field check for feature enabling
zimka Oct 9, 2017
c01427b
Change from djangoapp to package
zimka Oct 10, 2017
2e33fbc
Api permission change, add 'get user shift'
zimka Nov 30, 2017
0d1f011
Fix provider error for FieldData other than Lms
zimka Dec 1, 2017
6ac8ac8
Readme, docstrings and tests update
zimka Dec 4, 2017
5795675
Remove edx static from repo
zimka Dec 4, 2017
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
20 changes: 20 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Description
-----------
This is django app based on OpenEdx Ficus release `"open-release/ficus.2"
<https://github.com/edx/edx-platform/tree/open-release/ficus.2>`_
that should provide the way for student to move forward all due dates for given course according to the rules defined by the course staff.
Similar feature at the Coursera is called "Session Switch": when activated, course has several sessions with the same content but different deadlines and student can switch them at will. This feature can be useful when student have missed some deadlines but still wants to
finish the course and get credit.

There are several differences between this app and course rerun/CCX:

1. The content of the course is the same in all course shifts. Therefore it should be easier for staff to upgrade such course if necessary. It also doesn't spend additional resources.

2. Forum is shared between all course shifts.

3. Students can use this function when they want, and therefore course schedule becomes more flexible.

Details
-------
Feature is implemented via additional FieldOverrideProvider and CourseUserGroups, similar to the way it's done for 'INDIVIDUAL_DUE_DATES' feature.
Every course student is associated with some CourseUserGroup, and provider checks for membership and shift due dates accordingly.
118 changes: 118 additions & 0 deletions manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from datetime import timedelta
from logging import getLogger

from django.utils import timezone
from models import CourseShiftGroup, CourseShiftGroupMembership, CourseShiftSettings


date_now = lambda: timezone.now().date()
log = getLogger(__name__)


class CourseShiftManager(object):
"""
Provides the interface to perform operations on users and
course shifts: user transfer between shifts, due date calculation,
active shifts etc.
"""

def __init__(self, course_key):
self.course_key = course_key
self.settings = CourseShiftSettings.get_course_settings(self.course_key)

@property
def is_shift_enabled(self):
return self.settings.is_shift_enabled

def get_user_shift(self, user, course_key):
"""
Returns user's shift group for given course.
"""
if not self.settings.is_shift_enabled:
return

membership = CourseShiftGroupMembership.get_user_membership(user, course_key)
if membership:
return membership.course_shift_group

def get_all_shifts(self):
return CourseShiftGroup.get_course_shifts(self.course_key)

def get_active_shifts(self, user=None):
"""
Returns shifts that are are active at this moment according to the settings,
i.e. enrollment have started but haven't finished yet.
If user is given and he has membership all started shifts are considered
as active
"""
if not self.settings.is_shift_enabled:
return []
all_shifts = CourseShiftGroup.get_course_shifts(self.course_key)
if not all_shifts:
return []

now = date_now()
active_shifts = []
current_start_date = None
if user:
current_group = self.get_user_shift(user, self.course_key)
current_start_date = current_group and current_group.start_date

for shift in all_shifts:
enroll_start = shift.start_date - timedelta(days=self.settings.enroll_before_days)
enroll_finish = shift.start_date + timedelta(days=self.settings.enroll_after_days)
if current_start_date and current_start_date < shift.start_date:
enroll_finish = now

if enroll_start < now <= enroll_finish:
active_shifts.append(shift)

return active_shifts

def sign_user_on_shift(self, user, shift, course_key):
"""
Transfers user to given shift group. User's enrollment is not checked
because at course enrollment user should be firstly transfered to shift and
only then enrolled on course.
:param user: user to enroll on shift
:param shift: CourseShiftGroup to enroll
:param course_key: to which course shift_to (and shift_from if not None) belongs
"""
if shift.course_key != course_key:
raise ValueError("Shift's course_key: '{}', given course_key:'{}'".format(
str(shift.course_key),
str(course_key)
))

membership = CourseShiftGroupMembership.get_user_membership(user=user, course_key=course_key)
shift_from = membership and membership.course_shift_group
if shift_from == shift:
return membership

active_shifts = self.get_active_shifts(user)
if shift not in active_shifts:
raise ValueError("Shift {} is not in active shifts: {}".format(
str(shift),
str(active_shifts)
))

return CourseShiftGroupMembership.transfer_user(user, shift_from, shift)

def create_shift(self, start_date):
"""
Creates plan with given start date.
"""
if not self.settings.is_shift_enabled:
return ValueError("Can't create shift: feature is turned off for course")
if self.settings.is_autostart:
raise ValueError("Can't create shift in autostart mode")

name = self.settings.build_name(start_date)
days_shift = self.settings.calculate_days_add(start_date)
shift, created = CourseShiftGroup.create(
name=name,
course_key=self.course_key,
start_date=start_date,
days_shift=days_shift
)
return shift
Copy link
Author

Choose a reason for hiding this comment

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

пустая строка тут нужна :)

Loading