Source

audrid / audrid / models.py

Full commit
# coding: utf-8

from audrid import (app, db)
from audrid.utils import (random_id, random_id_fun)
from flask import (session)
import datetime
import json

class User(db.Model):
    """ A application user.
    """
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(80), nullable=False)
    
    email = db.Column(db.String(120), unique=True, nullable=False)
    group = db.Column(db.String(120), nullable=False)

    active = db.Column(db.Boolean, nullable=False, default=True)

    def __init__(self, username=None, email=None, password=None, group='guest', active=True):
        self.username = username
        self.password = password
        self.email = email
        self.group = group
        self.active = active

    def __repr__(self):
        return '<User %s, %s>' % (self.username, self.email)

class Pool(db.Model):
    """ A task pool.
    """
    __tablename__ = 'pools'

    id = db.Column(db.String(16), primary_key=True)
    body = db.Column(db.LargeBinary, nullable=False, default=json.dumps({}))
    deleted = db.Column(db.Boolean, nullable=False, default=False)

    def __init__(self, id=None, body=None, deleted=False):
        self.id = id or random_id()
        self.body = body
        self.deleted = deleted

    def __repr__(self):
        if self.deleted:
            return '<Pool %s/%s/%s>' % (self.id, len(self.tasks()), self.deleted)
        return '<Pool %s/%s>' % (self.id, len(self.tasks()))

    def as_dict(self):
        return {
            "id" : self.id,
            "body" : json.loads(self.body),
            "deleted" : self.deleted
        }

    def tasks(self, id=None):
        """ Return a list of tasks or, if an id is given the task with that id.
        """
        if id == None:
            return json.loads(self.body).get('tasks', [])
        for task in json.loads(self.body).get('tasks', []):
            if task['id'] == id:
                return task
        return None

    def append_task(self, task):
        """ Perform append.
        """
        current = json.loads(self.body)
        current['tasks'].append(task)
        self.body = json.dumps(current)

    def remove_task(self, task_id):
        """ Perform a remove, given a task id. """
        current = json.loads(self.body)
        tasks = []
        for task in current['tasks']:
            if not task['id'] == task_id:
                tasks.append(task)
        current['tasks'] = tasks
        self.body = json.dumps(current)


class PoolVersion(db.Model):
    """ Everytime a Pool is saved, updated or deleted a pool version is saved, too.
    """
    __tablename__ = 'pool_versions'

    added_id = db.Column(db.Integer, primary_key=True) 
    
    id = db.Column(db.String(16), db.ForeignKey('pools.id'), nullable=False)
    pool = db.relationship('Pool', backref=db.backref('versions', lazy='dynamic'))
    version = db.Column(db.Integer, nullable=False)

    body = db.Column(db.LargeBinary, nullable=False)
    updated_at = db.Column(db.DateTime, nullable=False)
    updated_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    comment = db.Column(db.Text)

    def __init__(self, id=None, body=None, updated_by=None, comment=None):
        upcoming_id = 1
        last = PoolVersion.query.filter_by(id=id).order_by(
            PoolVersion.version.desc()).first()
        if not last == None:
            upcoming_id = last.version + 1

        self.id = id
        self.version = upcoming_id
        self.body = body
        self.updated_by = updated_by
        self.updated_at = datetime.datetime.now()
        self.comment = comment

    def __repr__(self):
        return '<PoolVersion %s.%s>' % (self.id, self.version)

    def as_dict(self):
        return { 
            "id" : self.id, 
            "version" : self.version, 
            "body" : json.loads(self.body),
            "updated_at" : self.updated_at.isoformat(),
            "updated_by" : self.updated_by,
            "comment" : self.comment,
        }

class Exam(db.Model):
    """ An exam.
    """
    __tablename__ = 'exams'

    id = db.Column(db.Integer, primary_key=True)    
    
    pool_version_id = db.Column(db.Integer, db.ForeignKey('pool_versions.added_id'), nullable=False)
    pool_version = db.relationship('PoolVersion', 
        primaryjoin='Exam.pool_version_id==PoolVersion.added_id')
    
    name = db.Column(db.String(80), unique=True, nullable=False)
    description = db.Column(db.Text)
    duration = db.Column(db.Integer, nullable=False, default=45) # in minutes

    deleted = db.Column(db.Boolean, nullable=False, default=False)

    def __init__(self, pool_id=None, version=None, name=None, description=None, duration=None):
        if version == None:
            version = PoolVersion.query.filter_by(id=pool_id).order_by(PoolVersion.version.desc()).first().version
        self.pool_version = PoolVersion.query.filter_by(id=pool_id).filter_by(version=version).first()
        self.name = name
        self.description = description
        self.duration = duration

    def __repr__(self):
        return '<Exam %s/%s.%s/%s>' % (self.id, self.pool_version.id, self.pool_version.version, self.name)    

    def as_dict(self):
        return {
            "id" : self.id,
            "pool_id" : self.pool_version.id,
            "pool_version" : self.pool_version.version,
            "name" : self.name,
            "description" : self.description,
            "duration" : self.duration,
            "deleted" : self.deleted,
        }

class Audit(db.Model):
    """ A concrete exam.
    """
    __tablename__ = 'audits'
    
    id = db.Column(db.Integer, primary_key=True)    

    exam_id = db.Column(db.Integer, db.ForeignKey('exams.id'), nullable=False)
    exam = db.relationship('Exam', backref=db.backref('audits', lazy='dynamic'))

    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    user = db.relationship('User', backref=db.backref('audits', lazy='dynamic'))

    answers = db.Column(db.LargeBinary)

    status = db.Column(db.String(16), default='registered', nullable=False)

    registered_at = db.Column(db.DateTime(), nullable=False)
    started_at = db.Column(db.DateTime(), nullable=True)
    finished_at = db.Column(db.DateTime(), nullable=True)
    corrected_at = db.Column(db.DateTime(), nullable=True)

    def __init__(self, exam_id=None, user_id=None):
        self.exam_id = exam_id
        self.user_id = user_id
        self.registered_at = datetime.datetime.now()

    def __repr__(self):
        return '<Audit %s, %s, %s>' % (self.id, self.exam, self.user)

    def as_dict(self):
        return {
            "id" : self.id,            
            "exam_id" : self.exam_id,
            "user_id" : self.user_id,
            
            "answers" : self.answers,

            "status" : self.status,            
            "registered_at" : str(self.registered_at),
            "started_at" : str(self.started_at),
            "finished_at" : str(self.finished_at),
            "corrected_at" : str(self.corrected_at),
        }