Loading portal/database/models.py +12 −1 Original line number Original line Diff line number Diff line Loading @@ -893,6 +893,12 @@ class Submission(db.Model, EntityBase): result = db.Column(db.String(length=10), default='none') result = db.Column(db.String(length=10), default='none') course = association_proxy('project', 'course') course = association_proxy('project', 'course') ALLOWED_TRANSITIONS = { SubmissionState.CANCELLED: [SubmissionState.READY, SubmissionState.CREATED, SubmissionState.QUEUED, SubmissionState.IN_PROGRESS], SubmissionState.READY: [SubmissionState.CREATED] } @property @property def log_name(self): def log_name(self): return f"{self.id} ({self.course.codename}/{self.project.codename} for " \ return f"{self.id} ({self.course.codename}/{self.project.codename} for " \ Loading @@ -900,7 +906,12 @@ class Submission(db.Model, EntityBase): def change_state(self, new_state): def change_state(self, new_state): # open to extension (state transition validation, ...) # open to extension (state transition validation, ...) if new_state in Submission.ALLOWED_TRANSITIONS.keys(): allow = Submission.ALLOWED_TRANSITIONS[new_state] if self.state not in allow: return False self.state = new_state self.state = new_state return True @property @property def message(self): def message(self): Loading portal/service/submissions.py +7 −5 Original line number Original line Diff line number Diff line Loading @@ -156,10 +156,12 @@ class SubmissionsService(GeneralService): raise errors.ForbiddenError(client, raise errors.ForbiddenError(client, note=f"User {client.log_name} cannot update " note=f"User {client.log_name} cannot update " f"state to other than CANCELLED.") f"state to other than CANCELLED.") self.submission.change_state(new_state) if self.submission.change_state(new_state): self.write_entity(self.submission) self.write_entity(self.submission) log.info(f"[UPDATE] Submission state {self.submission.log_name} " log.info(f"[UPDATE] Submission state {self.submission.log_name} " f"by {client.log_name} to {self.submission.state}") f"by {client.log_name} to {self.submission.state}") else: log.warning("[UPDATE] Submission state change is not possible") return self.submission return self.submission def cancel_submission(self): def cancel_submission(self): Loading tests/database/test_db.py +2 −2 Original line number Original line Diff line number Diff line Loading @@ -3,8 +3,8 @@ from datetime import MAXYEAR, MINYEAR, datetime, timedelta import pytest import pytest from sqlalchemy import exc from sqlalchemy import exc from portal.database.models import Client, ClientType, Course, Group, Project, ProjectState, Review, \ from portal.database.models import Client, ClientType, Course, Group, Project, ProjectState, \ ReviewItem, Role, Submission, User Review, ReviewItem, Role, Submission, User from portal.tools import time from portal.tools import time Loading tests/rest/test_submission.py +7 −7 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ def created_submission(rest_service, client) -> Submission: new_submission = rest_tools.extract_data(response) new_submission = rest_tools.extract_data(response) return rest_service.find.submission(new_submission['id']) return rest_service.find.submission(new_submission['id']) def test_list_all_avail(client): def test_list_all_avail(client): db_subm = Submission.query.all() db_subm = Submission.query.all() response = rest_tools.make_request(client, f'/submissions') response = rest_tools.make_request(client, f'/submissions') Loading Loading @@ -150,15 +151,14 @@ def test_read_state(client): # needs more tests for state transitions # needs more tests for state transitions def test_update_state(client): def test_update_state(client): submissions = Submission.query.all() request_dict = {"state": SubmissionState.CANCELLED.name} s = submissions[0] submission = Submission.query.filter_by(state=SubmissionState.IN_PROGRESS).first() request_dict = {"state": "CANCELLED"} response = rest_tools.make_request(client, f'/submissions/{submission.id}/state', json=request_dict, response = rest_tools.make_request(client, f'/submissions/{s.id}/state', json=request_dict, method='put') method='put') assert_response(response, 204) assert_response(response, 204) s_updated = Submission.query.all()[0] sub_up = Submission.query.filter_by(id=submission.id).first() assert s_updated.state == SubmissionState.CANCELLED assert sub_up.state == SubmissionState.CANCELLED # does not pass - needs a Storage mock or config # does not pass - needs a Storage mock or config Loading Loading
portal/database/models.py +12 −1 Original line number Original line Diff line number Diff line Loading @@ -893,6 +893,12 @@ class Submission(db.Model, EntityBase): result = db.Column(db.String(length=10), default='none') result = db.Column(db.String(length=10), default='none') course = association_proxy('project', 'course') course = association_proxy('project', 'course') ALLOWED_TRANSITIONS = { SubmissionState.CANCELLED: [SubmissionState.READY, SubmissionState.CREATED, SubmissionState.QUEUED, SubmissionState.IN_PROGRESS], SubmissionState.READY: [SubmissionState.CREATED] } @property @property def log_name(self): def log_name(self): return f"{self.id} ({self.course.codename}/{self.project.codename} for " \ return f"{self.id} ({self.course.codename}/{self.project.codename} for " \ Loading @@ -900,7 +906,12 @@ class Submission(db.Model, EntityBase): def change_state(self, new_state): def change_state(self, new_state): # open to extension (state transition validation, ...) # open to extension (state transition validation, ...) if new_state in Submission.ALLOWED_TRANSITIONS.keys(): allow = Submission.ALLOWED_TRANSITIONS[new_state] if self.state not in allow: return False self.state = new_state self.state = new_state return True @property @property def message(self): def message(self): Loading
portal/service/submissions.py +7 −5 Original line number Original line Diff line number Diff line Loading @@ -156,10 +156,12 @@ class SubmissionsService(GeneralService): raise errors.ForbiddenError(client, raise errors.ForbiddenError(client, note=f"User {client.log_name} cannot update " note=f"User {client.log_name} cannot update " f"state to other than CANCELLED.") f"state to other than CANCELLED.") self.submission.change_state(new_state) if self.submission.change_state(new_state): self.write_entity(self.submission) self.write_entity(self.submission) log.info(f"[UPDATE] Submission state {self.submission.log_name} " log.info(f"[UPDATE] Submission state {self.submission.log_name} " f"by {client.log_name} to {self.submission.state}") f"by {client.log_name} to {self.submission.state}") else: log.warning("[UPDATE] Submission state change is not possible") return self.submission return self.submission def cancel_submission(self): def cancel_submission(self): Loading
tests/database/test_db.py +2 −2 Original line number Original line Diff line number Diff line Loading @@ -3,8 +3,8 @@ from datetime import MAXYEAR, MINYEAR, datetime, timedelta import pytest import pytest from sqlalchemy import exc from sqlalchemy import exc from portal.database.models import Client, ClientType, Course, Group, Project, ProjectState, Review, \ from portal.database.models import Client, ClientType, Course, Group, Project, ProjectState, \ ReviewItem, Role, Submission, User Review, ReviewItem, Role, Submission, User from portal.tools import time from portal.tools import time Loading
tests/rest/test_submission.py +7 −7 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,7 @@ def created_submission(rest_service, client) -> Submission: new_submission = rest_tools.extract_data(response) new_submission = rest_tools.extract_data(response) return rest_service.find.submission(new_submission['id']) return rest_service.find.submission(new_submission['id']) def test_list_all_avail(client): def test_list_all_avail(client): db_subm = Submission.query.all() db_subm = Submission.query.all() response = rest_tools.make_request(client, f'/submissions') response = rest_tools.make_request(client, f'/submissions') Loading Loading @@ -150,15 +151,14 @@ def test_read_state(client): # needs more tests for state transitions # needs more tests for state transitions def test_update_state(client): def test_update_state(client): submissions = Submission.query.all() request_dict = {"state": SubmissionState.CANCELLED.name} s = submissions[0] submission = Submission.query.filter_by(state=SubmissionState.IN_PROGRESS).first() request_dict = {"state": "CANCELLED"} response = rest_tools.make_request(client, f'/submissions/{submission.id}/state', json=request_dict, response = rest_tools.make_request(client, f'/submissions/{s.id}/state', json=request_dict, method='put') method='put') assert_response(response, 204) assert_response(response, 204) s_updated = Submission.query.all()[0] sub_up = Submission.query.filter_by(id=submission.id).first() assert s_updated.state == SubmissionState.CANCELLED assert sub_up.state == SubmissionState.CANCELLED # does not pass - needs a Storage mock or config # does not pass - needs a Storage mock or config Loading