def __init__(self): super().__init__() self.moodle = MoodleDBSession() self.moodlemod = ModUserEnrollments() # Set up some things self.courses = [] for course in self.moodle.get_teaching_learning_courses(): self.courses.append(course.idnumber) self.groups = self.moodle.get_list_of_attributes('group', 'name')
from psmdlsyncer.models.datastores.autosend import AutoSendTree from psmdlsyncer.models.datastores.moodle import MoodleTree from psmdlsyncer.sql.MDB import MoodleDBSession from psmdlsyncer.php import ModUserEnrollments import re from collections import defaultdict if __name__ == "__main__": autosend = AutoSendTree() moodle = MoodleTree() moodle.process() autosend.process() dragonnet = MoodleDBSession() mod = ModUserEnrollments() results = dragonnet.get_timetable_data(active_only=False) TimetableInfo = dragonnet.table_string_to_class('ssis_timetable_info') # First thing we need to do is adjust the timetable info so that the comment # Has the section info reverse = {} for key, value in autosend.groups.section_maps.items(): reverse[value] = key for item in results: # Find the section info by looking through step-by-step if item.name in reverse: section = reverse[item.name] with dragonnet.DBSession() as session: # Get the object in the db, change the comment
from psmdlsyncer.sql import MoodleDBSession from psmdlsyncer.models.datastores.autosend import AutoSendTree from psmdlsyncer.php import ModUserEnrollments dry_run = True if __name__ == "__main__": dnet = MoodleDBSession() mod = ModUserEnrollments() not_students = [] cohorts = ["parentsALL", "teachersALL"] for cohort in cohorts: users = dnet.users_enrolled_in_this_cohort(cohort) not_students.extend([u.idnumber for u in users]) dnet = MoodleDBSession() enrollments = dnet.bell_schedule() count = 0 for enrollment in enrollments: if enrollment.rolename == "student" and enrollment.userID in not_students: count = count + 1 role = "parent" if enrollment.userID.endswith("P") else "teacher" dry_run and print(enrollment) # print("userId: {}; role {}".format(enrollment.userID, role)) not dry_run and mod.unenrol_user_from_course(enrollment.userID, enrollment.courseID) not dry_run and mod.enrol_user_into_course( enrollment.userID, enrollment.courseID, enrollment.groupName, enrollment.groupIdNumber, role )
from psmdlsyncer.php import ModUserEnrollments from psmdlsyncer.models.datastores.autosend import AutoSendTree if __name__ == "__main__": autosend = AutoSendTree() autosend.process() moodlemod = ModUserEnrollments() for student_key in autosend.students.get_keys(): student = autosend.students.get_key(student_key) for group in student.groups: moodlemod.add_user_to_group(student.idnumber, group.idnumber) for teacher_key in autosend.teachers.get_keys(): teacher = autosend.teachers.get_key(teacher_key) for group in teacher.groups: moodlemod.add_user_to_group(teacher.idnumber, group.idnumber) for parent_key in autosend.parents.get_keys(): parent = autosend.parents.get_key(parent_key) for group in parent.groups: moodlemod.add_user_to_group(parent.idnumber, group.idnumber)
class MoodleTemplate(DefaultTemplate): """ Unpacks the info that comes in and sends it on to the PHP routines that acutally does the work Note: If you want to have some sort of queuing feature that, say, makes sure that "new_group" gets called before "add_to_group" (to ensure it's already there when adding it) This is the place to do it. """ def __init__(self): super().__init__() self.moodle = MoodleDBSession() self.moodlemod = ModUserEnrollments() # Set up some things self.courses = [] for course in self.moodle.get_teaching_learning_courses(): self.courses.append(course.idnumber) self.groups = self.moodle.get_list_of_attributes('group', 'name') def course_exists(self, course_idnumber): return course_idnumber in self.courses def new_cohort(self, item): super().new_cohort(item) cohort_idnumber = item.param cohort_name = cohort_idnumber self.moodle.add_cohort(cohort_idnumber, cohort_name) def old_cohort(self, item): super().old_cohort(item) # Remove it? def new_student(self, item): """ """ user = self.moodle.wrap_no_result(self.moodle.get_user_from_idnumber, item.right.idnumber) if user: self.logger.warning("Putting existing student {} into the studentsALL group?".format(item.right)) if user.deleted == 1: self.moodle.undelete_user(user) self.moodlemod.add_user_to_cohort(item.right.idnumber, 'studentsALL') else: super().new_student(item) student = item.right self.moodlemod.new_student(student) def login_method_changed(self, item): """ """ user = item.right try: self.moodle.update_table('user', where={ 'idnumber':user.idnumber }, login_method=user.login_method) self.default_logger("Changed {} login method to {}".format(item.right, item.param)) except (NoResultFound, MultipleResultsFound): self.logger.warn("Could not update login_method field for user {}".format(user)) def check_for_allow_deletions(self): """ If there settings.ini file contains specific instructions to delete the accounts, then do so Otherwise assume False """ return config_get_section_attribute('MOODLE', 'deletion_mode') == 'hard_delete' def check_for_keep_username_startswith(self, user): with_what = config_get_section_attribute('MOODLE', 'keep_username_startswith') if not with_what: return False with_what = with_what.split(',') for this in with_what: if user.username.startswith(this): return True return False def remove_user_from_all_courses(self, user): for course in user.courses: self.moodlemod.deenrol_student_from_course(user.idnumber, course.idnumber) def remove_user_from_all_groups(self, user): """ Used in old_* accounts functions """ debug = config_get_section_attribute('DEBUGGING', 'inspect_soft_deletion_groups') for group in user.groups: self.logger.warning("Removing old_student {} from group {} ".format(user, group)) self.moodlemod.remove_user_from_group(user.idnumber, group.idnumber) def old_student(self, item): super().old_student(item) student = item.left if self.check_for_keep_username_startswith(student): self.default_logger('I {} am a sacred account, leave me alone!'.format(student)) return if self.check_for_allow_deletions(): # This is the hard delete mode here # This deletes the account, probably only need this once in a while # Main difference from soft delete is that it unenrols them from all courses, which can delete information self.moodlemod.delete_account(student.idnumber) else: # The following lot item is useful if you want to provide an admin with CSV file of students that # are going to be deleted, in transition from soft to hard delete #self.logger.warn(student.to_csv) # Now set the homeroom field to 'left' and remove them from any groups they are in # Doesn't delete the account, and doesn't unenrol them from courses, either # Which makes recovering them a simple matter. # try: # self.moodle.update_table('user', where={ # 'idnumber':student.idnumber # }, # deleted=1) # except (NoResultFound, MultipleResultsFound): # self.logger.warn("Did not update homeroom field for student {}".format(student)) # TODO: Make this a config item from the command line # try: # self.moodle.update_table('user', where={ # 'idnumber':student.idnumber # }, # deleted=1) # except (NoResultFound, MultipleResultsFound): # self.logger.warn("Coudefld not set deleted of student {} to 1".format(student)) # Remove from all groups as well? self.remove_user_from_all_groups(student) self.remove_user_from_all_courses(student) def old_teacher(self, item): return super().old_teacher(item) teacher = item.left if self.check_for_keep_username_startswith(teacher): self.default_logger('I {} am a sacred account, leave me alone!'.format(teacher)) return if self.check_for_allow_deletions(): self.moodlemod.delete_account(teacher.idnumber) else: # self.logger.warn('Deleting teacher: {}'.format(teacher)) # try: # self.moodle.update_table('user', where={ # 'idnumber':teacher.idnumber # }, # deleted=1) # except (NoResultFound, MultipleResultsFound): # self.logger.warn("Could not set deleted of teacher {} to 1".format(teacher)) self.remove_user_from_all_groups(teacher) self.remove_user_from_all_courses(teacher) def old_parent(self, item): super().old_parent(item) parent = item.left if self.check_for_keep_username_startswith(parent): self.default_logger('I {} am a sacred account, leave me alone!'.format(parent)) return if self.check_for_allow_deletions(): self.moodlemod.delete_account(parent.idnumber) else: # self.logger.warn('Deleting parent: {}'.format(parent)) # try: # self.moodle.update_table('user', where={ # 'idnumber':parent.idnumber # }, # deleted=1) # except NoResultFound: # self.logger.warn("Could not delete parent {}".format(parent)) # except MultipleResultsFound: # self.logger.warn('Multiple parent accounts for {}'.format(parent.idnumber)) self.remove_user_from_all_groups(parent) self.remove_user_from_all_courses(parent) def new_teacher(self, item): """ """ user = self.moodle.wrap_no_result(self.moodle.get_user_from_username, item.right.username) if user: self.logger.warning("Staff member with username {} already exists, setting PS ID to {}.".format(item.right.username, item.right.idnumber)) self.moodle.set_user_idnumber_from_username(item.right.username, item.right.idnumber) if user.deleted == 1: self.moodle.undelete_user(user) else: pass # super().new_teacher(item) # teacher = item.right # self.moodlemod.new_teacher(teacher) def new_parent(self, item): """ """ user = self.moodle.wrap_no_result(self.moodle.get_user_from_idnumber, item.right.idnumber) if user: if user.deleted == 1: self.moodle.undelete_user(user) self.logger.warning("Putting parent student {} into the parentsALL group".format(item.right)) self.moodlemod.add_user_to_cohort(item.right.idnumber, 'parentsALL') if self.moodle.wrap_no_result(self.moodle.get_user_from_username, item.right.username): self.logger.warning("This parent with guardian email {0} is not linked. Search PS for 'GuardianEmail contains {0}' and email results to Admissions".format(item.right.email)) else: super().new_parent(item) parent = item.right self.moodlemod.new_parent(parent) # Add to the appropriate cohort now to ensure it's working self.moodlemod.add_user_to_cohort(parent.idnumber, 'parentsALL') def new_group(self, item): """ Although we detect new groups, the right thing to do is actually to create the group, as they are needed, when enrolling users. That's because groups and courses are inexplicably linked together and we have to do the checks for groups when enrolling anyway so best is to do the creation there """ super().new_group(item) # output # def new_course(self, item): # super().new_course(item) # course = item.right # self.moodlemod.create_new_course(course.idnumber, course.name) def enrol_in_course(self, item): course_idnumber = item.param.course yes_no = course_idnumber in self.courses if yes_no: super().enrol_in_course(item) # for output return yes_no def enrol_student_into_course(self, item): student = item.right.idnumber course = item.param.course group = item.param.group self.moodlemod.enrol_student_into_course(student, course, group) # just pass the whole schedule object itself # if self.enrol_in_course(item): # for output and checking # self.moodlemod.enrol_student_into_course(student, course, group) # just pass the whole schedule object itself # else: # self.logger.debug("Did NOT enrol {} into course {}, because it does not exist in Moodle".format(item.right, course)) def enrol_teacher_into_course(self, item): teacher = item.right.idnumber course = item.param.course group = item.param.group self.moodlemod.enrol_teacher_into_course(teacher, course, group) # just pass the whole schedule object itself # if self.enrol_in_course(item): # for output and checking # self.moodlemod.enrol_teacher_into_course(teacher, course, group) # just pass the whole schedule object itself # else: # self.logger.debug("Did NOT enrol {} into course {}, because it does not exist in Moodle".format(item.right, course)) def enrol_parent_into_course(self, item): parent = item.right.idnumber course = item.param.course group = item.param.group self.moodlemod.enrol_parent_into_course(parent, course, group) # just pass the whole schedule object itself # if self.enrol_in_course(item): # for output and checking # self.moodlemod.enrol_parent_into_course(parent, course, group) # just pass the whole schedule object itself # else: # self.logger.debug("Did NOT enrol {} into course {}, because it does not exist in Moodle".format(item.right, course)) def deenrol_teacher_from_course(self, item): return super().deenrol_from_course(item) # for output user = item.right.idnumber course = item.param.course group = item.param.group.idnumber #self.moodlemod.deenrol_teacher_from_course(user, course) def deenrol_student_from_course(self, item): return user = item.right.idnumber course = item.param.course group = item.param.group.idnumber if hasattr(user, 'grade') and user.grade == 12: return super().deenrol_from_course(item) # for output self.moodlemod.deenrol_student_from_course(user, course) def deenrol_parent_from_course(self, item): return super().deenrol_from_course(item) # for output user = item.right.idnumber course = item.param.course group = item.param.group.idnumber self.moodlemod.deenrol_parent_from_course(user, course) def add_to_cohort(self, item): super().add_to_cohort(item) user = item.right.idnumber cohort = item.param self.moodlemod.add_user_to_cohort(user, cohort) def remove_from_cohort(self, item): super().remove_from_cohort(item) user = item.left.idnumber cohort = item.param self.moodlemod.remove_user_from_cohort(user, cohort) def new_group(self, item): if not item.right.course: self.default_logger("Did NOT add group {} because no course available".format(item.param)) return course = item.right.course group = item.right if group in self.groups: self.logger.debug("Did NOT add group {} because it's already there....".format(group, course_idnumber)) elif course.idnumber in self.courses: super().new_group(item) self.moodlemod.add_group(group.idnumber, group.name, course.idnumber) else: self.logger.debug("Did NOT add group {} because course {} does not exist.".format(group, course.idnumber)) def new_custom_profile_field(self, item): """ """ right = item.right name = right.idnumber self.default_logger("Found a new custom profile field {}".format(name)) self.moodle.make_new_custom_profile_field(name) def old_custom_profile_field(self, item): """ This actually means that a particular user has lost a particular profile field (It does NOT mean that this profile field should be deleted...) or does it? """ # not sure what to do yet def old_group(self, item): group = item.left course_idnumber = group.course_idnumber if course_idnumber not in self.courses: self.default_logger("Did NOT delete group {} because the correspoding course {} does not exist.".format(group, course_idnumber)) elif re.search('-[a-z]{1}$', group.idnumber): self.moodlemod.delete_group(group.idnumber, course_idnumber) else: self.default_logger("Did NOT delete group {} in {} because it looks like a one manually maintained.".format(group, course_idnumber)) def add_to_group(self, item): user = item.right group = item.param.group course = item.param.course if course in self.courses: super().add_to_group(item) # We don't actually need the course... self.moodlemod.add_user_to_group(user.idnumber, group.idnumber) #self.default_logger("Successfully put user {} into group {}".format(user, group)) else: self.logger.debug("Did NOT put {} in group {} because course {} does not exist.".format(user, group, course)) def remove_from_group(self, item): user = item.right.idnumber group = item.param.group course = item.param.course # We don't actually need the course... if not '-' in group.idnumber: # Must be a manual one, leave it alone return if group.idnumber.split('-') == 3: super().remove_from_group(item) self.moodlemod.remove_user_from_group(user, group.idnumber) else: # Take them out for now, this may need to change return super().remove_from_group(item) self.moodlemod.remove_user_from_group(user, group.idnumber) def username_changed(self, item): user = item.left idnumber = user.idnumber from_what = item.left.username to_what = item.right.username.strip() if user.idnumber.endswith('P'): # If two students do not have the same family ID, but contain the same guardian information # Then an error would result if we tried to change the username here # Because we cannot have two users with the same username if self.moodle.wrap_no_result(self.moodle.get_user_from_username, to_what): self.logger.critical("- Cannot change parent username for {} because username {} is already taken".format(user, to_what)) return # It's a parent, so we need to change the username and email, and inform them newpassword = str(random.randint(111111, 999999)) # generates pseudo-random 6 digit number self.moodlemod.change_parent_username(user.idnumber, to_what, newpassword) # Send username change with item.right in order to provide the right info inform.inform_parent_username_changed(item.right, newpassword) self.logger.warning('Parent {} username changed from {} to {} and password is {}'.format(user, from_what, to_what, newpassword)) elif hasattr(item.right, 'login_method') and item.right.login_method == 'nologin': # Just go ahead and change it automatically, no need to inform anyone or anything # because the account isn't active anyway # test for 'login_method' because teachers don't have that TODO: Add that to the model! super().username_changed(item) return # Just in case # TODO: Also update email field! #try: # self.moodle.update_table('user', where={ # 'idnumber':idnumber # }, # username=to_what) #except IntegrityError: # self.logger.warning('Got integrity error trying to change user {}\'s username to {}'.format(idnumber, to_what)) #except NoResultFound: # self.default_logger('Cannot change username for {} as not found in moodle: {}'.format(idnumber, item)) #super().username_changed(item) else: justgrade = functools.partial(re.sub, '[a-z_]', '') if justgrade(item.left.username) != justgrade(item.right.username): self.logger.critical("Grade change: Username {} has changed grade, needs username changed to {}".format(from_what, to_what)) else: msg = "Username {} needs his/her username changed manually to {} this happens when passport info gets changed".format(from_what, to_what) if '_' in from_what: if from_what.replace('_', '') == to_what: self.default_logger("Student {} with an underscore and whose username has NOT changed to {}.".format(from_what, to_what)) else: self.logger.warning(msg) else: self.logger.warning(msg) def custom_profile_value_changed(self, item): person = item.left.useridnumber field = item.param.field value = item.param.value self.moodle.set_user_custom_profile(person, field, value) def add_custom_profile_field_to_user(self, item): super().add_custom_profile_field_to_user(item) person = item.right.idnumber field = item.param.field value = item.param.value self.moodle.add_user_custom_profile(person, field, value) def homeroom_changed(self, item): user = item.left from_what = item.left.homeroom if user.kind == 'student': homeroom = item.param elif user.kind == 'parent': homeroom = ','.join(item.param) # if user.idnumber == '4340P': # from IPython import embed; # print('4340P') # embed() # exit() try: self.moodle.update_table('user', where={ 'idnumber':user.idnumber }, department=homeroom) super().homeroom_changed(item) except NoResultFound: self.default_logger('Could not change homeroom for {} as not found in moodle'.format(item)) def course_grade_changed(self, item): for i in range(len(item.param)): grade = item.param[i] field = 'grade{}'.format(i+1) exists = self.moodle.get_rows_in_table('course_ssis_metadata', courseid = item.left.database_id, field=field) if not exists: self.moodle.insert_table('course_ssis_metadata', courseid = item.left.database_id, field=field, value=grade) else: # we just need to update the existing one self.moodle.update_table('course_ssis_metadata', where = dict( courseid=item.left.database_id, field=field, ), value=grade ) def new_parent_link(self, item): """ Go through all the children and make the association """ super().new_parent_link(item) for child_idnumber in item.right.children: self.moodlemod.associate_child_to_parent(item.right.parent_idnumber, child_idnumber) def associate_child_to_parent(self, item): """ Go through all the children and make the association """ super().new_parent_link(item) for child_idnumber in item.right.children: self.moodlemod.associate_child_to_parent(item.right.parent_idnumber, child_idnumber) def deassociate_child_from_parent(self, item): return super().deassociate_child_from_parent(item) def new_mrbs_editor(self, item): super().new_mrbs_editor(item) self.moodle.add_mrbs_editor(item.param) def new_timetable(self, item): pass # meaningless def old_timetable(self, item): pass # meaningless def new_timetable_data(self, item): super().new_timetable_data(item) #self.moodle.add_timetable_data(item.right) def old_timetable_data(self, item): super().old_timetable_data(item) #self.moodle.set_timetable_data_inactive(item.left) def new_course_metadata(self, item): super().new_course_metadata(item) self.moodle.add_course_metadata(item.right) def new_online_portfolio(self, item): super().new_online_portfolio(item)