class Authorship(db.Model): __tablename__ = 'authorship' id = db.Column(db.Integer, primary_key=True, autoincrement=True) course_id = db.Column(db.Integer, db.ForeignKey('course.id', ondelete="CASCADE")) author_id = db.Column(db.Integer)
class TextStepModel(db.Model): __tablename__ = 'text_step' base_step_id = db.Column(db.Integer, db.ForeignKey('step.id', ondelete='CASCADE')) text = db.Column(db.String()) audio = db.Column(db.String()) id = db.Column(db.Integer, primary_key=True, autoincrement=True)
class PurchasedCoursesModel(db.Model): __tablename__ = 'purchased_courses' id = db.Column(db.Integer, primary_key=True, autoincrement=True) course_id = db.Column(db.Integer, db.ForeignKey('course.id', ondelete="SET NULL")) user_id = db.Column(db.Integer, nullable=False) datetime = db.Column(db.DateTime, nullable=False, default=datetime.now()) _idx1 = db.Index('purchased_courses_id', 'user_id', 'course_id', unique=True)
class HomeworkStepModel(db.Model): __tablename__ = 'homework_step' base_step_id = db.Column(db.Integer, db.ForeignKey('step.id', ondelete='CASCADE')) id = db.Column(db.Integer, primary_key=True, autoincrement=True) homework_id = db.Column(db.Integer) @property async def homework_content(self): from Everland import rpc_client body = json.dumps({'homework_id': self.homework_id}) response = json.loads(await rpc_client.call(body, 'prod_rpc_homeworks')) if response['status'] != 200: raise ServerException(1, response['description'], '') return response['data']
class PaymentModel(db.Model): __tablename__ = 'payment' id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_id = db.Column(db.Integer, nullable=False) course_id = db.Column(db.Integer, db.ForeignKey('course.id', ondelete="SET NULL")) order_id = db.Column(db.String(36), index=True, nullable=False) datetime = db.Column(db.DateTime, nullable=False, default=datetime.now()) amount = db.Column(db.Float, nullable=False) _idx1 = db.Index('payment_id', 'user_id', 'course_id', unique=True)
class PassedModuleUser(db.Model): __tablename__ = 'passed_module_user' module_id = db.Column(db.Integer, db.ForeignKey('module.id', ondelete="SET NULL")) user_id = db.Column(db.Integer)
class ModuleModel(db.Model): __tablename__ = 'module' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(128)) number = db.Column(db.Integer, nullable=False) course_id = db.Column(db.Integer, db.ForeignKey('course.id', ondelete='CASCADE')) async def previous_modules_is_passed(self, user_id: int): if user_id is None: return True course = await self.get_course() all_modules = await course.modules for module in all_modules: if module.id == self.id: return True if not await module.is_passed_by_user(user_id): return False @property async def lessons(self): return await LessonModel.query.\ where(LessonModel.module_id == self.id).\ order_by(LessonModel.number).\ gino.all() async def get_course(self) -> 'CourseModel': from ..Course.models import CourseModel course = await CourseModel.get(self.course_id) return course async def belongs_to(self, user_id: int) -> bool: course = await self.get_course() return await course.belongs_to(user_id) @staticmethod async def cherry_pick_lesson(pick_from_module_id: int, pick_to_module_id: int, current_number: int, new_number: int): if pick_from_module_id == pick_to_module_id: if current_number < new_number: await LessonModel.update. \ values(number=LessonModel.number - 1). \ where(LessonModel.module_id == pick_to_module_id). \ where(LessonModel.number > current_number). \ where(LessonModel.number <= new_number). \ gino.status() elif current_number > new_number: await LessonModel.update. \ values(number=LessonModel.number + 1). \ where(LessonModel.module_id == pick_to_module_id). \ where(LessonModel.number < current_number). \ where(LessonModel.number >= new_number). \ gino.status() else: await LessonModel.update. \ values(number=LessonModel.number - 1). \ where(LessonModel.module_id == pick_from_module_id). \ where(LessonModel.number > current_number). \ gino.status() await LessonModel.update. \ values(number=LessonModel.number + 1). \ where(LessonModel.module_id == pick_to_module_id). \ where(LessonModel.number >= new_number). \ gino.status() @property async def is_passed(self): pass async def is_passed_by_user(self, user_id=None): if user_id is None: return None for lesson in await self.lessons: if not (await lesson.is_passed_by_user(user_id=user_id)): return False return True
class CourseModel(db.Model): __tablename__ = 'course' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(128), nullable=False) specialty_id = db.Column(db.Integer, db.ForeignKey('specialty.id', ondelete='CASCADE'), nullable=False) description = db.Column(db.String(2048)) annotations = db.Column(db.String(1024)) difficulty = db.Column(db.Integer, nullable=False) recommendations = db.Column(db.String(256)) required_materials = db.Column(db.String(256)) video = db.Column(db.String(1024)) logo = db.Column(db.String()) cost = db.Column(db.Integer, nullable=True, default=None) development = db.Column(db.Boolean, nullable=False, default=True) confirmed = db.Column(db.Boolean, nullable=False, default=False) time_for_course = db.Column(db.Integer, nullable=True) creation_date = db.Column(db.Date, nullable=False, default=date.today()) async def belongs_to(self, author_id: int) -> bool: """ Проверка на принадлежность курса пользователя :param author_id: ID пользователя :return: """ author = await Authorship.query. \ where(Authorship.course_id == self.id). \ where(Authorship.author_id == author_id). \ gino.first() return author is not None @property async def is_bought(self): pass async def is_bought_by_user(self, user_id=None): if user_id is None: return None return (await PurchasedCoursesModel.query.where( PurchasedCoursesModel.course_id == self.id and\ PurchasedCoursesModel.user_id == user_id ).gino.first()) is not None @property async def authors(self): return list(map(lambda row: row.author_id, await Authorship.query.where( Authorship.course_id == self.id ).gino.all() )) # @property # async def count_studying_students(self): # rows = await StudyCourseUser.query. \ # where(StudyCourseUser.course_id == self.id). \ # gino.all() # return len(rows) # @property # async def count_passing_students(self): # rows = await PassedCourseUser.query. \ # where(PassedCourseUser.course_id == self.id). \ # gino.all() # return len(rows) @property async def modules(self): return await ModuleModel.query. \ where(ModuleModel.course_id == self.id). \ order_by(ModuleModel.number). \ gino.all() @property async def rate(self): return 0 @staticmethod async def cherry_pick_module( pick_from_course_id: int, pick_to_course_id: int, current_number:int, new_number: int): if pick_from_course_id == pick_to_course_id: if current_number < new_number: await ModuleModel.update.\ values(number=ModuleModel.number - 1).\ where(ModuleModel.course_id == pick_to_course_id).\ where(ModuleModel.number > current_number).\ where(ModuleModel.number <= new_number).\ gino.status() elif current_number > new_number: await ModuleModel.update. \ values(number=ModuleModel.number + 1). \ where(ModuleModel.course_id == pick_to_course_id). \ where(ModuleModel.number < current_number). \ where(ModuleModel.number >= new_number). \ gino.status() else: await ModuleModel.update. \ values(number=ModuleModel.number - 1). \ where(ModuleModel.course_id == pick_from_course_id). \ where(ModuleModel.number > current_number). \ gino.status() await ModuleModel.update. \ values(number=ModuleModel.number + 1). \ where(ModuleModel.course_id == pick_to_course_id). \ where(ModuleModel.number >= new_number). \ gino.status()
class Specialty(db.Model): __tablename__ = 'specialty' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(), nullable=False)
class BaseStepModel(db.Model): __tablename__ = 'step' id = db.Column(db.Integer, primary_key=True, autoincrement=True) number = db.Column(db.Integer, nullable=False) step_type = db.Column(db.Enum(StepType), nullable=False) lesson_id = db.Column(db.Integer, db.ForeignKey('lesson.id', ondelete='CASCADE')) async def get_lesson(self): from ..Lesson.models import LessonModel return await LessonModel.get(self.lesson_id) async def previous_steps_is_passed(self, user_id: int): if user_id is None: return True lesson = await self.get_lesson() if not (await lesson.previous_lessons_is_passed(user_id)): return False previous_steps = await db.select([BaseStepModel.id, PassedStepUser.step_id]). \ select_from(BaseStepModel. outerjoin(PassedStepUser, (and_(PassedStepUser.step_id == BaseStepModel.id, PassedStepUser.user_id == user_id))) ). \ where(BaseStepModel.lesson_id == self.lesson_id). \ order_by(BaseStepModel.number). \ gino.all() for step in previous_steps: if step[0] == self.id: return True if step[1] is None: return False @property async def instance(self): if self.step_type == StepType.Test: return await TestStepModel.query.where( TestStepModel.base_step_id == self.id).gino.first() elif self.step_type == StepType.Video: return await VideoStepModel.query.where( VideoStepModel.base_step_id == self.id).gino.first() elif self.step_type == StepType.Text: return await TextStepModel.query.where( TextStepModel.base_step_id == self.id).gino.first() elif self.step_type == StepType.Homework: return await HomeworkStepModel.query.where( HomeworkStepModel.base_step_id == self.id).gino.first() async def get_course_id(self) -> int: from ..Course.models import CourseModel from ..Module.models import ModuleModel from ..Lesson.models import LessonModel courses_id = await db.select([CourseModel.id]). \ select_from(CourseModel. join(ModuleModel). join(LessonModel). join(BaseStepModel) ). \ where(BaseStepModel.id == self.id). \ gino.first() return courses_id[0] async def get_course(self) -> 'CourseModel': from ..Course.models import CourseModel course_id = await self.get_course_id() course = await CourseModel.get(course_id) return course async def belongs_to(self, user_id: int) -> bool: course = await self.get_course() return await course.belongs_to(user_id) @property async def is_passed(self): pass async def is_passed_by_user(self, user_id=None): if user_id is None: return None row = await PassedStepUser.query.\ where(PassedStepUser.step_id == self.id).\ where(PassedStepUser.user_id == user_id).\ gino.first() return row is not None
class PassedStepUser(db.Model): __tablename__ = 'passed_step_user' step_id = db.Column(db.Integer, db.ForeignKey('step.id', ondelete="CASCADE")) user_id = db.Column(db.Integer)
class LessonModel(db.Model): __tablename__ = 'lesson' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(128)) number = db.Column(db.Integer, nullable=False) module_id = db.Column(db.Integer, db.ForeignKey('module.id', ondelete='CASCADE')) async def previous_lessons_is_passed(self, user_id): if user_id is None: return True module = await self.get_module() if not (await module.previous_modules_is_passed(user_id)): return False all_lessons = await module.lessons for lesson in all_lessons: if lesson.id == self.id: return True if not await lesson.is_passed_by_user(user_id): return False @property async def steps(self): return await BaseStepModel.query.where( BaseStepModel.lesson_id == self.id ).order_by( BaseStepModel.number ).gino.all() async def get_module(self) -> 'ModuleModel': from ..Module.models import ModuleModel module = await ModuleModel.get(self.module_id) return module async def get_course_id(self) -> int: from ..Course.models import CourseModel from ..Module.models import ModuleModel courses_id = await db.select([CourseModel.id]). \ select_from(CourseModel.join(ModuleModel).join(LessonModel)).where(LessonModel.id == self.id).gino.first() return courses_id[0] async def get_course(self) -> 'CourseModel': from ..Course.models import CourseModel course_id = await self.get_course_id() course = await CourseModel.get(course_id) return course async def belongs_to(self, user_id: int) -> bool: course = await self.get_course() return await course.belongs_to(user_id) @staticmethod async def cherry_pick_step( pick_from_lesson_id: int, pick_to_lesson: int, current_number: int, new_number: int): if pick_from_lesson_id == pick_to_lesson: if current_number < new_number: await BaseStepModel.update. \ values(number=BaseStepModel.number - 1). \ where(BaseStepModel.lesson_id == pick_to_lesson). \ where(BaseStepModel.number > current_number). \ where(BaseStepModel.number <= new_number). \ gino.status() elif current_number > new_number: await BaseStepModel.update. \ values(number=BaseStepModel.number + 1). \ where(BaseStepModel.lesson_id == pick_to_lesson). \ where(BaseStepModel.number < current_number). \ where(BaseStepModel.number >= new_number). \ gino.status() else: await BaseStepModel.update. \ values(number=BaseStepModel.number - 1). \ where(BaseStepModel.lesson_id == pick_from_lesson_id). \ where(BaseStepModel.number > current_number). \ gino.status() await BaseStepModel.update. \ values(number=BaseStepModel.number + 1). \ where(BaseStepModel.lesson_id == pick_to_lesson). \ where(BaseStepModel.number >= new_number). \ gino.status() @property async def is_passed(self): pass async def is_passed_by_user(self, user_id=None): # TODO: Оптимизировать # Lambda is not await :c # return all(map( # lambda step: await step.is_passed_by_user(user_id), # self.steps # )) if user_id is None: return None for step in await self.steps: if not (await step.is_passed_by_user(user_id=user_id)): return False return True