139 lines
6.7 KiB
Python
139 lines
6.7 KiB
Python
from ..extensions import db
|
|
from ..tools.forms import JsonEncodedDict
|
|
from ..tools.logs import write
|
|
|
|
from flask_login import current_user
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
from datetime import date, datetime
|
|
import secrets
|
|
from uuid import uuid4
|
|
|
|
class Test(db.Model):
|
|
|
|
id = db.Column(db.String(36), primary_key=True)
|
|
code = db.Column(db.String(36), nullable=False)
|
|
start_date = db.Column(db.DateTime, nullable=True)
|
|
end_date = db.Column(db.DateTime, nullable=True)
|
|
time_limit = db.Column(db.Integer, nullable=True)
|
|
creator_id = db.Column(db.String(36), db.ForeignKey('user.id'))
|
|
dataset_id = db.Column(db.String(36), db.ForeignKey('dataset.id'))
|
|
adjustments = db.Column(JsonEncodedDict, nullable=True)
|
|
entries = db.relationship('Entry', backref='test')
|
|
|
|
def __repr__(self):
|
|
return f'<Test with code {self.get_code()} was created by {current_user.get_username()}.>'
|
|
|
|
@property
|
|
def generate_id(self): raise AttributeError('generate_id is not a readable attribute.')
|
|
|
|
generate_id.setter
|
|
def generate_id(self): self.id = uuid4().hex
|
|
|
|
@property
|
|
def generate_code(self): raise AttributeError('generate_code is not a readable attribute.')
|
|
|
|
generate_code.setter
|
|
def generate_code(self): self.code = secrets.token_hex(6).lower()
|
|
|
|
def get_code(self):
|
|
code = self.code.upper()
|
|
return '—'.join([code[:4], code[4:8], code[8:]])
|
|
|
|
def create(self):
|
|
self.generate_id()
|
|
self.generate_code()
|
|
self.creator = current_user
|
|
errors = []
|
|
if self.start_date.date() < date.today():
|
|
errors.append('The start date cannot be in the past.')
|
|
if self.end_date.date() < date.today():
|
|
errors.append('The expiry date cannot be in the past.')
|
|
if self.end_date < self.start_date:
|
|
errors.append('The expiry date cannot be before the start date.')
|
|
if errors:
|
|
return False, errors
|
|
try:
|
|
db.session.add(self)
|
|
db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when creating test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Test with code {self.get_code()} created by {current_user.get_username()}.')
|
|
return True, f'Test with code {self.get_code()} has been created.'
|
|
|
|
def delete(self):
|
|
if self.entries: return False, f'Cannot delete a test with submitted entries.'
|
|
db.session.delete(self)
|
|
try: db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when deleting test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Test with code {self.get_code()} has been deleted by {current_user.get_username()}.')
|
|
return True, f'Test with code {self.get_code()} has been deleted.'
|
|
|
|
def start(self):
|
|
now = datetime.now()
|
|
if self.start_date.date() > now.date():
|
|
self.start_date = now
|
|
try: db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when launching test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Test with code {self.get_code()} has been started by {current_user.get_username()}.')
|
|
return True, f'Test with code {self.get_code()} has been started.'
|
|
return False, f'Test with code {self.get_code()} has already started.'
|
|
|
|
def end(self):
|
|
now = datetime.now()
|
|
if self.end_date >= now:
|
|
self.end_date = now
|
|
try: db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when closing test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Test with code {self.get_code()} ended by {current_user.get_username()}.')
|
|
return True, f'Test with code {self.get_code()} has been ended.'
|
|
return False, f'Test with code {self.get_code()} has already ended.'
|
|
|
|
def add_adjustment(self, time:int):
|
|
adjustments = self.adjustments if self.adjustments is not None else {}
|
|
code = secrets.token_hex(3).lower()
|
|
adjustments[code] = time
|
|
self.adjustments = adjustments
|
|
try: db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when adding adjustment to test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Time adjustment for {time} minutes with code {code} added to test {self.get_code()} by {current_user.get_username()}.')
|
|
return True, f'Time adjustment for {time} minutes added to test {self.get_code()}. This can be accessed using the user code {code.upper()}.'
|
|
|
|
def remove_adjustment(self, code:str):
|
|
if not self.adjustments: return False, f'There are no adjustments configured for test {self.get_code()}.'
|
|
self.adjustments.pop(code)
|
|
if not self.adjustments: self.adjustments = None
|
|
try: db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when deleting adjustment from test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Time adjustment for with code {code} has been removed from test {self.get_code()} by {current_user.get_username()}.')
|
|
return True, f'Time adjustment for with code {code} has been removed from test {self.get_code()}.'
|
|
|
|
def update(self, start_date:datetime=None, end_date:datetime=None, time_limit:int=None):
|
|
if not start_date and not end_date and time_limit is None: return False, 'There were no changes requested.'
|
|
if start_date: self.start_date = start_date
|
|
if end_date: self.end_date = end_date
|
|
if time_limit is not None: self.time_limit = time_limit
|
|
try: db.session.commit()
|
|
except SQLAlchemyError as exception:
|
|
db.session.rollback()
|
|
write('system.log', f'Database error when updating test {self.get_code()}: {exception}')
|
|
return False, f'Database error: {exception}'
|
|
write('system.log', f'Test with code {self.get_code()} has been updated by user {current_user.get_username()}.')
|
|
return True, f'Test with code {self.get_code()} has been updated by.' |