Загрузка данных


from datetime import date

from flask import (
    Blueprint, render_template, request, abort, redirect, url_for, flash
)
from flask_login import login_required, current_user

from app.models import db, Intern, Attendance, User
from app.services.statistics import intern_stats, monthly_calendar
from app.utils import parse_period

interns_bp = Blueprint("interns", __name__, url_prefix="/interns")


def _can_access(intern: Intern) -> bool:
    return current_user.is_admin or intern.mentor_id == current_user.id


@interns_bp.route("/")
@login_required
def list_interns():
    mentor_id = request.args.get("mentor_id", type=int)
    q = Intern.query
    if current_user.is_admin:
        if mentor_id:
            q = q.filter_by(mentor_id=mentor_id)
    else:
        q = q.filter_by(mentor_id=current_user.id)

    interns = q.order_by(Intern.full_name).all()
    mentors = User.query.filter_by(role="mentor").order_by(User.full_name).all() \
        if current_user.is_admin else []

    return render_template(
        "interns/list.html",
        interns=interns, mentors=mentors,
        selected_mentor=mentor_id,
    )


@interns_bp.route("/<int:intern_id>")
@login_required
def detail(intern_id: int):
    intern = Intern.query.get_or_404(intern_id)
    if not _can_access(intern):
        abort(403)

    today = date.today()
    year = request.args.get("year", today.year, type=int)
    month = request.args.get("month", today.month, type=int)

    if month < 1:
        month, year = 12, year - 1
    elif month > 12:
        month, year = 1, year + 1

    weeks = monthly_calendar(year, month)

    records = Attendance.query.filter_by(intern_id=intern_id).all()
    att_map = {
        r.date.day: r
        for r in records
        if r.date.year == year and r.date.month == month
    }

    date_from, date_to = parse_period(default_days=30)
    stats_period = intern_stats(intern_id, date_from, date_to)
    stats_all = intern_stats(intern_id)

    prev_year, prev_month = (year, month - 1) if month > 1 else (year - 1, 12)
    next_year, next_month = (year, month + 1) if month < 12 else (year + 1, 1)

    return render_template(
        "interns/detail.html",
        intern=intern,
        weeks=weeks, year=year, month=month,
        att_map=att_map,
        stats_period=stats_period,
        stats_all=stats_all,
        today=today,
        date_from=date_from, date_to=date_to,
        prev_year=prev_year, prev_month=prev_month,
        next_year=next_year, next_month=next_month,
    )


@interns_bp.route("/create", methods=["POST"])
@login_required
def create():
    if not current_user.is_admin:
        abort(403)
    # Базовая форма (используется из админского интерфейса)
    full_name = request.form.get("full_name", "").strip()
    mentor_id = request.form.get("mentor_id", type=int)
    if not full_name or not mentor_id:
        flash("Заполните ФИО и наставника", "danger")
        return redirect(url_for("interns.list_interns"))

    intern = Intern(
        full_name=full_name,
        direction=request.form.get("direction", "").strip() or None,
        email=request.form.get("email", "").strip() or None,
        phone=request.form.get("phone", "").strip() or None,
        mentor_id=mentor_id,
    )
    db.session.add(intern)
    db.session.commit()
    flash("Стажёр добавлен", "success")
    return redirect(url_for("interns.detail", intern_id=intern.id))