Compare commits

...

2 Commits

Author SHA1 Message Date
Malar Kannan 0f8c70a38e completed attendance get/update 2017-09-01 00:37:59 +05:30
Malar Kannan fe97494629 1. code clean up
2. get_attendance wip
2017-08-31 22:07:58 +05:30
3 changed files with 122 additions and 51 deletions

View File

@ -6,4 +6,15 @@ 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,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,
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

129
server.py
View File

@ -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,22 +33,33 @@ 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(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)
db.session.commit()
for s in range(5):
stu = Student("TestStudent#{}-Class{}".format(s,g_cls.id), g_cls.id)
db.session.add(stu)
user_datastore.create_user(
email='user@example.com', password='password')
@ -55,11 +68,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 +77,105 @@ 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)
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
presense_keys = [str(i).replace('Presence.', '').upper() for i in Presence]
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
@app.route('/api/attendance/<update_type>', methods=['POST'])
# @login_required
def update_attendance(update_type):
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_map.values():
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/<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'])
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'