routes.py 10.9 KB
from pprint import pprint

from flask import render_template, make_response, current_app, redirect, url_for, request, flash
from flask_login import login_required, current_user

from . import bp

from app.models import Agent, Project, Service, Capacity, Period, db, Company, AgentGrade, AgentStatus, AgentBap, \
    Charge, Category, Label
from app import db_mgr
from app.auth.routes import role_required


@bp.before_request
def site_login():
    try:
        if current_app.config['SITE_LOGIN'] \
                and not current_user.is_authenticated:
            return redirect(url_for('auth.login'))
    except KeyError:
        # no such config, juste ignore
        pass


@bp.before_request
def catch_all_route():
    current_app.logger.debug(f"{request.method} {request.path}")


@bp.route('/')
def index():
    return render_template('index.html', subtitle="Page d'accueil")


@bp.route('/services')
@role_required('service')
def services():
    # get services list
    all_services = Service.query.order_by(Service.name).all()
    num_services = len(all_services)
    # pass to template
    return render_template('services.html', subtitle="Liste des services ({})".format(num_services),
                           services=all_services)


@bp.route('/projects')
@role_required('project')
def projects():
    # get projects list
    all_projects = db_mgr.projects()
    num_projects = len(all_projects)
    # pass to template
    return render_template('projects.html', subtitle="Liste des projets ({})".format(num_projects),
                           projects=all_projects)


@bp.route('/projects/stats')
@role_required('project')
def projects_stats():
    num_projects = len(Project.query.all())
    return render_template('projects_stats.html', subtitle="Statistiques des projets ({})".format(num_projects))


@bp.route('/agents')
@role_required('project')
def agents():
    # get agents list
    all_agents = db_mgr.agents()
    num_agents = len(all_agents)
    # pass to template
    return render_template('agents.html', subtitle="Liste des agents ({})".format(num_agents),
                           agents=all_agents)


@bp.route('/capacities')
@login_required
def capacities():
    # get capacities list
    all_capacities = Capacity.query.order_by(Capacity.name).all()
    num_capacities = len(all_capacities)
    # pass to template
    return render_template('capacities.html', subtitle="Liste des fonctions ({})".format(num_capacities),
                           capacities=all_capacities)


@bp.route('/labels')
@login_required
def labels():
    # get labels list
    all_labels = Label.query.order_by(Label.name).all()
    num_labels = len(all_labels)
    # pass to template
    return render_template('labels.html', subtitle="Liste des labels ({})".format(num_labels),
                           labels=all_labels)


@bp.route('/categories')
@login_required
def categories():
    # get categories list
    all_categories = Category.query.order_by(Category.name).all()
    num_categories = len(all_categories)
    # pass to template
    return render_template('categories.html', subtitle="Liste des categories ({})".format(num_categories),
                           categories=all_categories)


@bp.route('/periods')
@login_required
def periods():
    # get categories list
    all_periods = Period.query.order_by(Period.name).all()
    num_periods = len(all_periods)
    # pass to template
    return render_template('periods.html', subtitle="Liste des périodes ({})".format(num_periods),
                           periods=all_periods)


@bp.route('/project/<project_id>')
@role_required('project')
def project(project_id):
    # TODO: am i the project manager ?
    this_project = Project.query.get(int(project_id))
    charges_table = db_mgr.charges_by_project(project_id)
    return render_template('project.html',
                           project=this_project.to_struct(),
                           charges=charges_table,
                           subtitle="{}".format(this_project.name))


@bp.route('/agent/<agent_id>')
@role_required('agent')
def agent(agent_id):
    # TODO: am i the agent, the service or project manager , or the admin ?
    this_agent = Agent.query.get(int(agent_id))
    charges_table = db_mgr.charges_by_agent_tabled(agent_id)
    return render_template('agent.html',
                           agent=this_agent,
                           charges=charges_table,
                           subtitle=f"{this_agent.fullname}")


# - - - - - - - - - - - - - - - - - - - -  FORMS  - - - - - - - - - - - - - - - - - - - - #
@bp.route('/label/create', methods=('POST', 'GET'))
@bp.route('/label/<label_id>/edit', methods=('POST', 'GET'))
@role_required('admin')
def label_edit(label_id=None):
    label_struct = None
    return render_template('label_form.html', label=label_struct)


@bp.route('/category/create', methods=('POST', 'GET'))
@bp.route('/category/<label_id>/edit', methods=('POST', 'GET'))
@role_required('admin')
def category_edit(category_id=None):
    category_struct = None
    return render_template('category_form.html', category=category_struct)


@bp.route('/project/create', methods=('POST', 'GET'))
@bp.route('/project/<project_id>/edit', methods=('POST', 'GET'))
@role_required('service')
def project_edit(project_id=None):
    if request.method == 'GET':
        if project_id:
            this_project = Project.query.get(int(project_id))
        else:
            this_project = Project()
        project_struct = this_project.to_struct()
        categories = db_mgr.category_labels()
        return render_template('project_form.html', project=project_struct,
                               categories=categories)
    elif request.method == 'POST':
        try:
            project_id = request.form['project_id']
        except KeyError:
            project_id = None
        if project_id:
            # then update existing
            this_project = Project.query.get(int(project_id))
            done_string = "mis à jour."
        else:
            # or create from scratch
            this_project = Project()
            done_string = "ajouté."
        # fill orm with form and write to db
        this_project.from_request(request)
        db.session.add(this_project)
        db.session.commit()
        # we're done
        flash(f"Project {this_project.name} (#{this_project.id}) " + done_string)
        return redirect(url_for('main.project', project_id=this_project.id))


@bp.route('/agent/create', methods=('POST', 'GET'))
@bp.route('/agent/<agent_id>/edit', methods=('POST', 'GET'))
@role_required('service')
def agent_edit(agent_id=None):
    # Make the form, filled with existing agent if updating
    #
    if request.method == 'GET':
        companies = Company.query.all()
        grades = AgentGrade.query.all()
        statuses = AgentStatus.query.all()
        baps = AgentBap.query.all()
        if agent_id:
            this_agent = Agent.query.get(int(agent_id))
        else:
            this_agent = Agent()
        # export to structure for jinja display
        agent_struct = this_agent.to_struct()
        return render_template('agent_form.html', agent=agent_struct,
                               companies=companies,
                               statuses=statuses,
                               baps=baps,
                               grades=grades)
    # Or submit for db writing
    #
    elif request.method == 'POST':
        try:
            agent_id = request.form['agent_id']
        except KeyError:
            agent_id = None
        if agent_id:
            # then update existing
            this_agent = Agent.query.get(int(agent_id))
            done_string = "mis à jour."
        else:
            # or create from scratch
            this_agent = Agent()
            done_string = "ajouté."
        # fill orm with form and write to db
        this_agent.from_request(request)
        db.session.add(this_agent)
        db.session.commit()
        # we're done
        flash(f"Agent {this_agent.fullname} (#{this_agent.id}) " + done_string)
        return redirect(url_for('main.agent', agent_id=this_agent.id))


@bp.route('/charge/add', methods=('POST', 'GET'))
@role_required('service')
def charge_add():
    if request.method == 'GET':
        try:
            this_agent = Agent.query.get(int(request.args['agent_id']))
        except KeyError:
            this_agent = None
        try:
            this_project = Project.query.get(int(request.args['project_id']))
        except KeyError:
            this_project = None
        this_agents = Agent.query.order_by(Agent.firstname).all()
        this_projects = Project.query.order_by(Project.name).all()
        this_services = Service.query.order_by(Service.name).all()
        this_periods = Period.query.order_by(Period.id).all()
        this_capacities = Capacity.query.order_by(Capacity.name).all()
        return render_template('charge_form.html', subtitle="Affecter un agent",
                               agent=this_agent,
                               project=this_project,
                               projects=this_projects,
                               services=this_services,
                               periods=this_periods,
                               capacities=this_capacities,
                               agents=this_agents)
    elif request.method == 'POST':
        this_agent = Agent.query.get(request.form.get('agent_id'))
        this_charge = Charge()
        this_charge.from_request(request)
        db.session.add(this_charge)
        db.session.commit()
        flash(f"Nouvelle charge pour l'agent {this_agent.fullname}")
        return redirect(url_for('main.agent', agent_id=this_agent.id))


# - - - - - - - - - - - - - - - - - - - -  REST API - - - - - - - - - - - - - - - - - - - -

@bp.route('/charge/project/<project_id>/<category>')
@role_required('project')
def charge_project_csv(project_id, category):
    csv_table = []
    for line in db_mgr.charges_by_project_stacked(project_id, category):
        line = [cell.replace(",", "-") for cell in line]
        line_string = ",".join(line)
        csv_table.append(line_string)
    resp = make_response("\n".join(csv_table))
    resp.headers['Content-Type'] = 'text/plain;charset=utf8'
    return resp


@bp.route('/charge/agent/<agent_id>')
@role_required('service')
def charge_agent_csv(agent_id):
    csv_table = []
    for line in db_mgr.charges_by_agent_stacked(agent_id):
        line = [cell.replace(",", "-") for cell in line]
        line_string = ",".join(line)
        csv_table.append(line_string)
    resp = make_response("\n".join(csv_table))
    resp.headers['Content-Type'] = 'text/plain;charset=utf8'
    return resp


@bp.route('/charge/projects')
@role_required('project')
def projects_stats_csv():
    csv_table = []
    for line in db_mgr.charges_for_projects_stacked():
        line = [cell.replace(",", "-") for cell in line]
        line_string = ",".join(line)
        csv_table.append(line_string)
    resp = make_response("\n".join(csv_table))
    resp.headers['Content-Type'] = 'text/plain;charset=utf8'
    return resp