Compare commits

..

No commits in common. "0f8c70a38ea02370f5dae7f294f2dbf7add502b3" and "6c3a6c28d17168a289b993114c6c710c7a141439" have entirely different histories.

3 changed files with 51 additions and 122 deletions

View File

@ -6,15 +6,4 @@ 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=2&start_time=now&end_time=now"`
`http --session=./session.json GET "http://127.0.0.1:5000/api/attendance/student?identifier=3&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"`

View File

@ -1,40 +1,32 @@
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)
@ -43,19 +35,16 @@ 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())
@ -63,7 +52,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

131
server.py
View File

@ -1,10 +1,8 @@
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 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_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
@ -33,33 +31,22 @@ 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)
json_cont = {'Content-Type': 'application/json'}
resp = lambda val,code: (json.dumps({'status': val}), code, json_cont)
presense_map = {i:str(i).replace('Presence.', '').upper() for i in Presence}
@app.before_first_request
def create_test_data():
try:
db.drop_all()
db.create_all()
for i in range(3):
for i in range(12):
g_cls = Gradeclass("Class {}".format(i))
db.session.add(g_cls)
db.session.commit()
for s in range(5):
stu = Student("TestStudent#{}-Class{}".format(s,g_cls.id), g_cls.id)
for s in range(10):
stu = Student("TestStudent#{}-Class{}".format(s,i), g_cls.id)
db.session.add(stu)
user_datastore.create_user(
email='user@example.com', password='password')
@ -68,6 +55,11 @@ 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
@ -77,105 +69,64 @@ def parse_time(time_str):
pass
return time
def compute_attendance(request_type,object_id, start_time, end_time):
def get_record(req_type,obj_id):
attend = AttendanceUpdate.query.filter(
AttendanceUpdate.update_type == req_type
).filter(
AttendanceUpdate.value_identifier == obj_id
).filter(
func.date(AttendanceUpdate.time) >= start_time.date()
).filter(
func.date(AttendanceUpdate.time) >= end_time.date()
).first()
return attend
pres_rec = None
if request_type == 'student':
stud_rec = get_record('student',object_id)
stud = Student.query.get(object_id)
pres_rec = stud_rec if stud_rec else get_record('class',stud.gradeclass_id)
if request_type == 'class':
pres_rec = get_record(request_type,object_id)
return presense_map[pres_rec.presence].lower() if pres_rec else 'no_records'
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
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:
pres = compute_attendance(update_type,object_id,start_time,end_time)
ret_data = resp(pres,200)
return ret_data
presense_keys = [str(i).replace('Presence.', '').upper() for i in Presence]
def update_attendance(update_type, request):
@app.route('/api/attendance/<update_type>', methods=['POST'])
# @login_required
def update_attendance(update_type):
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 = resp('invalid',400)
if validate_attend(
update_type, object_id
) and presence and attend_time and presence.upper() in presense_map.values():
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:
pres_enum = Presence[presence.upper()]
upsert_attendance(update_type, object_id, attend_time, pres_enum)
ret_data = resp('updated',200)
return ret_data
ret_data = (json.dumps({'status': 'updated'}),200)
return api_resp(*ret_data)
@app.route('/api/attendance/<update_type>', 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'])
@app.route('/api/login',methods=['POST'])
def login():
username = request.form.get('username', None)
password = request.form.get('password', None)
ret_data = (json.dumps({'status': 'failed'}), 401, json_cont)
print(username,password)
ret_data = (json.dumps({'status': 'failed'}),401)
if username and password:
user = User.query.filter(User.email == username).first()
if not user:
ret_data = resp('notfound',401)
elif verify_and_update_password(password, user):
ret_data = (json.dumps({'status': 'notfound'}),401)
elif verify_and_update_password(password,user):
login_user(user)
ret_data = resp('success',200)
ret_data = (json.dumps({'status': 'success'}),200)
return ret_data
@app.route('/')
def home():
return 'hello'