diff --git a/README.md b/README.md index 7292855..53c810b 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,14 @@ start the server by running `$http --session=./session.json -f POST http://127.0.0.1:5000/api/login username=user@example.com password=password` ### Update Attendance +Student : `$http --session=./session.json -f POST http://127.0.0.1:5000/api/attendance/student presence=absent identifier=2 time=now` +Class : +`http --session=./session.json -f POST http://127.0.0.1:5000/api/attendance/class presence=present identifier=1 time=now` + + +### Get Attendance +Student: +`http --session=./session.json GET "http://127.0.0.1:5000/api/attendance/student?identifier=1&start_time=now&end_time=now"` +Class: +`http --session=./session.json GET "http://127.0.0.1:5000/api/attendance/class?identifier=1&start_time=now&end_time=now"` diff --git a/models.py b/models.py index e62350a..0480a99 100644 --- a/models.py +++ b/models.py @@ -1,32 +1,40 @@ from flask_sqlalchemy import SQLAlchemy -from flask_security import UserMixin,RoleMixin -from enum import Enum,unique +from flask_security import UserMixin, RoleMixin +from enum import Enum, unique from datetime import datetime db = SQLAlchemy() roles_users = db.Table('roles_users', - db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), - db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) + db.Column('user_id', + db.Integer(), db.ForeignKey('user.id')), + db.Column('role_id', + db.Integer(), db.ForeignKey('role.id'))) + class Role(db.Model, RoleMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) + class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) confirmed_at = db.Column(db.DateTime()) - roles = db.relationship('Role', secondary=roles_users, - backref=db.backref('users', lazy='dynamic')) + roles = db.relationship( + 'Role', + secondary=roles_users, + backref=db.backref('users', lazy='dynamic')) + @unique class Presence(Enum): """docstring for ResultType.""" - PRESENT,ABSENT,SICK,VACATION = range(4) + PRESENT, ABSENT, SICK, VACATION = range(4) + class Gradeclass(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -35,16 +43,19 @@ class Gradeclass(db.Model): def __init__(self, class_name): self.class_name = class_name + class Student(db.Model): id = db.Column(db.Integer, primary_key=True) student_name = db.Column(db.String(255)) gradeclass_id = db.Column(db.Integer, db.ForeignKey('gradeclass.id')) - gradeclass = db.relationship('Gradeclass',backref=db.backref('gradeclass', lazy='dynamic')) + gradeclass = db.relationship( + 'Gradeclass', backref=db.backref('gradeclass', lazy='dynamic')) - def __init__(self, student_name,gradeclass_id): + def __init__(self, student_name, gradeclass_id): self.student_name = student_name self.gradeclass_id = gradeclass_id + class AttendanceUpdate(db.Model): id = db.Column(db.Integer, primary_key=True) time = db.Column(db.DateTime()) @@ -52,7 +63,7 @@ class AttendanceUpdate(db.Model): update_type = db.Column(db.String(10)) value_identifier = db.Column(db.Integer) - def __init__(self, update_type, value_identifier,time,presence): + def __init__(self, update_type, value_identifier, time, presence): self.update_type = update_type self.value_identifier = value_identifier self.presence = presence diff --git a/server.py b/server.py index 2eb8752..a80c385 100644 --- a/server.py +++ b/server.py @@ -1,8 +1,10 @@ -from flask import Flask, Blueprint, request, Response -from flask_security import SQLAlchemyUserDatastore, login_required, current_user, Security -from flask_security.utils import verify_and_update_password,login_user +from flask import Flask, Blueprint, request +from flask_security import (SQLAlchemyUserDatastore, login_required, + current_user, Security) +from flask_security.utils import verify_and_update_password, login_user from flask_restless import APIManager, ProcessingException -from models import db, User, Role, Gradeclass, Student, AttendanceUpdate, Presence +from models import (db, User, Role, Gradeclass, Student, AttendanceUpdate, + Presence) from sqlalchemy import func import json from datetime import datetime, date @@ -31,10 +33,16 @@ def auth_func(*args, **kwargs): verify_logged_id = dict(GET_SINGLE=[auth_func], GET_MANY=[auth_func]) manager = APIManager(app, flask_sqlalchemy_db=db) -manager.create_api(Student, methods=[ - 'GET', 'PUT'], results_per_page=5, preprocessors=verify_logged_id) -manager.create_api(Gradeclass, methods=[ - 'GET', 'PUT'], results_per_page=5, preprocessors=verify_logged_id) +manager.create_api( + Student, + methods=['GET', 'PUT'], + results_per_page=5, + preprocessors=verify_logged_id) +manager.create_api( + Gradeclass, + methods=['GET', 'PUT'], + results_per_page=5, + preprocessors=verify_logged_id) @app.before_first_request @@ -42,11 +50,11 @@ def create_test_data(): try: db.drop_all() db.create_all() - for i in range(12): + for i in range(3): g_cls = Gradeclass("Class {}".format(i)) db.session.add(g_cls) - for s in range(10): - stu = Student("TestStudent#{}-Class{}".format(s,i), g_cls.id) + for s in range(5): + stu = Student("TestStudent#{}-Class{}".format(s, i), g_cls.id) db.session.add(stu) user_datastore.create_user( email='user@example.com', password='password') @@ -55,11 +63,6 @@ def create_test_data(): pass -def api_resp(data, code=200): - return Response(response=data, - status=code, - mimetype="application/json") - def parse_time(time_str): utc_now = (time_str and time_str == 'now') or not time_str time = datetime.utcnow() if utc_now else None @@ -69,64 +72,88 @@ def parse_time(time_str): pass return time + def upsert_attendance(update_type, object_id, attend_time, pres_enum): existing = AttendanceUpdate.query.filter( - AttendanceUpdate.update_type == update_type - ).filter( - AttendanceUpdate.value_identifier == object_id - ).filter( - func.date(AttendanceUpdate.time) == attend_time.date() - ).first() + AttendanceUpdate.update_type == update_type).filter( + AttendanceUpdate.value_identifier == object_id).filter( + func.date( + AttendanceUpdate.time) == attend_time.date()).first() if existing: existing.presence = pres_enum else: - new_entry = AttendanceUpdate( - update_type, object_id, attend_time, pres_enum) + new_entry = AttendanceUpdate(update_type, object_id, attend_time, + pres_enum) db.session.add(new_entry) db.session.commit() + def validate_attend(update_type, object_id): - return True + # return True if update_type in ['class', 'student'] and object_id: - g_cls_found = update_type == 'class' and Gradeclass.query.get(object_id) - stud_found = update_type == 'student' and Student.query.get(object_id) + g_cls_found = update_type == 'class' and Gradeclass.query.get( + object_id) + stud_found = update_type == 'student' and Student.query.get(object_id) return g_cls_found or stud_found else: return False +json_cont = {'Content-Type': 'application/json'} +resp = lambda val,code: (json.dumps({'status': val}), code, json_cont) presense_keys = [str(i).replace('Presence.', '').upper() for i in Presence] -@app.route('/api/attendance/', methods=['POST']) -# @login_required -def update_attendance(update_type): +def get_attendance(update_type, request): + object_id = request.args.get('identifier', None) + start_timestr = request.args.get('start_time', None) + end_timestr = request.args.get('end_time', None) + start_time, end_time = parse_time(start_timestr), parse_time(end_timestr) + ret_data = resp('invalid',400) + if validate_attend(update_type, object_id) and start_time and end_time: + ret_data = resp('present',200) + return ret_data + + +def update_attendance(update_type, request): object_id = request.form.get('identifier', None) presence = request.form.get('presence', None) attend_str = request.form.get('time', None) attend_time = parse_time(attend_str) - ret_data = (json.dumps({'status': 'invalid'}),400) - if validate_attend(update_type, object_id) and presence and attend_time and presence.upper() in presense_keys: + ret_data = resp('invalid',400) + if validate_attend( + update_type, object_id + ) and presence and attend_time and presence.upper() in presense_keys: pres_enum = Presence[presence.upper()] upsert_attendance(update_type, object_id, attend_time, pres_enum) - ret_data = (json.dumps({'status': 'updated'}),200) - return api_resp(*ret_data) + ret_data = resp('updated',200) + return ret_data -@app.route('/api/login',methods=['POST']) + +@app.route('/api/attendance/', methods=['GET', 'POST']) +@login_required +def attendance(update_type): + if request.method == 'GET': + return get_attendance(update_type, request) + elif request.method == 'POST': + return update_attendance(update_type, request) + + +@app.route('/api/login', methods=['POST']) def login(): username = request.form.get('username', None) password = request.form.get('password', None) - print(username,password) - ret_data = (json.dumps({'status': 'failed'}),401) + ret_data = (json.dumps({'status': 'failed'}), 401, json_cont) if username and password: user = User.query.filter(User.email == username).first() if not user: - ret_data = (json.dumps({'status': 'notfound'}),401) - elif verify_and_update_password(password,user): + ret_data = resp('notfound',401) + elif verify_and_update_password(password, user): login_user(user) - ret_data = (json.dumps({'status': 'success'}),200) + ret_data = resp('success',200) return ret_data + @app.route('/') def home(): return 'hello'