61 lines
1.8 KiB
Python
61 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
from flask import Blueprint, abort, jsonify, redirect, render_template, request, url_for
|
|
from flask_login import current_user
|
|
|
|
from app.extensions import db
|
|
from app.models import AttendanceEvent, AttendanceType, Person, Role
|
|
from app.services.attendance import last_presence_summary, record_attendance
|
|
from app.services.security import roles_required
|
|
|
|
bp = Blueprint("attendance", __name__, url_prefix="/attendance")
|
|
|
|
|
|
@bp.get("/")
|
|
@roles_required(Role.ADMIN, Role.OPERATOR, Role.VIEWER)
|
|
def index():
|
|
events = AttendanceEvent.query.order_by(AttendanceEvent.occurred_at.desc()).limit(250).all()
|
|
return render_template("attendance/index.html", events=events)
|
|
|
|
|
|
@bp.get("/kiosk")
|
|
@roles_required(Role.ADMIN, Role.OPERATOR)
|
|
def kiosk():
|
|
return render_template("attendance/kiosk.html")
|
|
|
|
|
|
@bp.post("/events")
|
|
@roles_required(Role.ADMIN, Role.OPERATOR)
|
|
def create_event():
|
|
person_id = request.form.get("person_id", type=int)
|
|
raw_event_type = request.form.get("event_type", "")
|
|
confidence = request.form.get("confidence", type=float)
|
|
|
|
person = db.session.get(Person, person_id) if person_id else None
|
|
if not person or not person.active:
|
|
abort(404)
|
|
|
|
try:
|
|
event_type = AttendanceType(raw_event_type)
|
|
except ValueError:
|
|
abort(400)
|
|
|
|
event = record_attendance(
|
|
person,
|
|
event_type,
|
|
created_by_id=current_user.id,
|
|
confidence=confidence,
|
|
source="web-kiosk",
|
|
)
|
|
|
|
if request.accept_mimetypes.accept_json:
|
|
return jsonify(
|
|
{
|
|
"id": event.id,
|
|
"event_type": event.type_label,
|
|
"occurred_at": event.occurred_at.strftime("%Y-%m-%d %H:%M"),
|
|
"summary": last_presence_summary(person),
|
|
}
|
|
)
|
|
return redirect(url_for("attendance.index"))
|