bump project

This commit is contained in:
2026-05-01 21:24:21 +03:30
parent dc4b1a1400
commit 139b3e26da
83 changed files with 2455 additions and 18349 deletions

84
app/people/routes.py Normal file
View File

@@ -0,0 +1,84 @@
from __future__ import annotations
from flask import Blueprint, abort, flash, redirect, render_template, request, url_for
from app.extensions import db
from app.models import FaceEncoding, Person, Role
from app.people.forms import PersonForm
from app.services.attendance import last_presence_summary
from app.services.recognition import RecognitionUnavailable, encode_uploaded_image
from app.services.security import roles_required
bp = Blueprint("people", __name__, url_prefix="/people")
@bp.get("/")
@roles_required(Role.ADMIN, Role.OPERATOR, Role.VIEWER)
def index():
people = Person.query.order_by(Person.full_name.asc()).all()
return render_template("people/index.html", people=people)
@bp.route("/new", methods=["GET", "POST"])
@roles_required(Role.ADMIN, Role.OPERATOR)
def new_person():
form = PersonForm()
if form.validate_on_submit():
files = [field.data for field in (form.photo_1, form.photo_2, form.photo_3, form.photo_4) if field.data]
files = [file for file in files if file.filename]
if not files:
flash("Upload at least one reference photo.", "danger")
return render_template("people/form.html", form=form)
try:
vectors = [encode_uploaded_image(file) for file in files]
except RecognitionUnavailable as exc:
flash(str(exc), "danger")
return render_template("people/form.html", form=form), 503
except ValueError as exc:
flash(str(exc), "danger")
return render_template("people/form.html", form=form)
person = Person(
full_name=form.full_name.data.strip(),
employee_id=form.employee_id.data.strip(),
notes=form.notes.data.strip() or None,
)
for slot, vector in enumerate(vectors, start=1):
encoding = FaceEncoding(image_slot=slot)
encoding.vector = vector
person.face_encodings.append(encoding)
db.session.add(person)
db.session.commit()
flash(f"{person.full_name} has been enrolled.", "success")
return redirect(url_for("people.detail", person_id=person.id))
return render_template("people/form.html", form=form)
@bp.get("/<int:person_id>")
@roles_required(Role.ADMIN, Role.OPERATOR, Role.VIEWER)
def detail(person_id: int):
person = db.session.get(Person, person_id)
if not person:
abort(404)
events = person.attendance_events[:]
events.sort(key=lambda event: event.occurred_at, reverse=True)
return render_template(
"people/detail.html",
person=person,
events=events[:20],
presence_summary=last_presence_summary(person),
)
@bp.post("/<int:person_id>/toggle")
@roles_required(Role.ADMIN, Role.OPERATOR)
def toggle_person(person_id: int):
person = db.session.get(Person, person_id)
if not person:
abort(404)
person.active = not person.active
db.session.commit()
flash(f"{person.full_name} is now {'active' if person.active else 'inactive'}.", "success")
return redirect(request.referrer or url_for("people.index"))