Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

completed assignment #156

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ def _set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()

with app.app_context():
from core import server
# db.create_all()

1 change: 1 addition & 0 deletions core/apis/assignments/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .student import student_assignments_resources
from .teacher import teacher_assignments_resources
from .principal import principal_assignments_resources
68 changes: 68 additions & 0 deletions core/apis/assignments/principal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from flask import Blueprint
from core import db
from core.apis import decorators
from core.apis.responses import APIResponse
from core.models.assignments import Assignment
from core.models.teachers import Teacher
import logging

from .schema import AssignmentSchema, AssignmentGradeSchema, TeacherSchema

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Define the blueprint for principal-specific APIs
principal_assignments_resources = Blueprint('principal_assignments_resources', __name__)

### 1. GET /principal/assignments
@principal_assignments_resources.route('/assignments', methods=['GET'], strict_slashes=False)
@decorators.authenticate_principal
def list_assignments(p):
"""Returns list of submitted and graded assignments"""
assignments = Assignment.query.filter(Assignment.state.in_(['SUBMITTED', 'GRADED'])).all()
assignments_dump = AssignmentSchema().dump(assignments, many=True)
return APIResponse.respond(data=assignments_dump)

### 2. GET /principal/teachers
@principal_assignments_resources.route('/teachers', methods=['GET'], strict_slashes=False)
@decorators.authenticate_principal
def list_teachers(p):
"""Returns list of all teachers"""
teachers = Teacher.query.all()
teachers_dump = TeacherSchema().dump(teachers, many=True)
return APIResponse.respond(data=teachers_dump)

### 3. POST /principal/assignments/grade
@principal_assignments_resources.route('/assignments/grade', methods=['POST'], strict_slashes=False)
@decorators.accept_payload
@decorators.authenticate_principal
def grade_assignment(p, incoming_payload):
"""Grade or re-grade an assignment"""
grade_assignment_payload = AssignmentGradeSchema().load(incoming_payload)

assignment = Assignment.query.get(grade_assignment_payload.id)

if not assignment:
return APIResponse.respond_with_error('Assignment not found', 404)

# Ensure the assignment is in a submitted state before grading
if assignment.state != 'SUBMITTED':
return APIResponse.respond_with_error('Assignment cannot be graded in its current state', 400)

# Update the grade and state of the assignment
assignment.grade = grade_assignment_payload.grade
assignment.state = 'GRADED'

# Commit changes to the database
try:
db.session.commit()
logger.info(f'Assignment {assignment.id} graded with {assignment.grade}')
except Exception as e:
db.session.rollback()
logger.error(f'Error grading assignment {assignment.id}: {e}')
return APIResponse.respond_with_error('Failed to grade assignment', 500)

assignment_dump = AssignmentSchema().dump(assignment)

return APIResponse.respond(data=assignment_dump, message='Assignment graded successfully.')
4 changes: 4 additions & 0 deletions core/apis/assignments/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ class Meta:
def initiate_class(self, data_dict, many, partial):
# pylint: disable=unused-argument,no-self-use
return GeneralObject(**data_dict)
class TeacherSchema(Schema):
id = fields.Int()
name = fields.Str()
# Add other fields as necessary
18 changes: 18 additions & 0 deletions core/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os

class Config:
SQLALCHEMY_DATABASE_URI = 'sqlite:///./store.sqlite3'
SQLALCHEMY_ECHO = False
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = os.environ.get('SECRET_KEY', 'default-secret-key')

class DevelopmentConfig(Config):
DEBUG = True

class ProductionConfig(Config):
DEBUG = False

config_by_name = {
'development': DevelopmentConfig,
'production': ProductionConfig
}
5 changes: 5 additions & 0 deletions core/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .assignments import Assignment
from .principals import Principal
from .students import Student
from .teachers import Teacher
from .users import User
3 changes: 2 additions & 1 deletion core/server.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from flask import jsonify
from marshmallow.exceptions import ValidationError
from core import app
from core.apis.assignments import student_assignments_resources, teacher_assignments_resources
from core.apis.assignments import student_assignments_resources, teacher_assignments_resources, principal_assignments_resources
from core.libs import helpers
from core.libs.exceptions import FyleError
from werkzeug.exceptions import HTTPException
Expand All @@ -10,6 +10,7 @@

app.register_blueprint(student_assignments_resources, url_prefix='/student')
app.register_blueprint(teacher_assignments_resources, url_prefix='/teacher')
app.register_blueprint(principal_assignments_resources, url_prefix='/principal')


@app.route('/')
Expand Down
5 changes: 5 additions & 0 deletions run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from core import app


if __name__ == '__main__':
app.run(debug=True)
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
-- Write query to find the number of grade A's given by the teacher who has graded the most assignments
SELECT COUNT(*) AS grade_A_count
FROM assignments
WHERE grade = 'A'
AND teacher_id = (
SELECT teacher_id
FROM assignments
WHERE state = 'GRADED'
GROUP BY teacher_id
ORDER BY COUNT(*) DESC
LIMIT 1
);
4 changes: 4 additions & 0 deletions tests/SQL/number_of_graded_assignments_for_each_student.sql
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
-- Write query to get number of graded assignments for each student:
SELECT student_id, COUNT(*) AS graded_assignments_count
FROM assignments
WHERE state = 'GRADED'
GROUP BY student_id;
17 changes: 17 additions & 0 deletions tests/principals_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,20 @@ def test_regrade_assignment(client, h_principal):

assert response.json['data']['state'] == AssignmentStateEnum.GRADED.value
assert response.json['data']['grade'] == GradeEnum.B

def test_list_assignments_principal(client, h_principal):
response = client.get('/principal/assignments', headers=h_principal)
assert response.status_code == 200
assert 'data' in response.json
for assignment in response.json['data']:
assert assignment['state'] in ['SUBMITTED', 'GRADED']

def test_list_assignments(client, h_principal):
response = client.get('/principal/assignments', headers=h_principal)
assert response.status_code == 200
assert 'data' in response.json

def test_grade_assignment_success(client, h_teacher_1):
response = client.post('/teacher/assignments/grade', headers=h_teacher_1, json={"id": 1, "grade": "A"})
assert response.status_code == 200
assert response.json['data']['grade'] == 'A'