import os from config import Config from datetime import datetime, date import glob import shutil from flask import render_template, redirect, url_for, request, flash, send_file, abort from flask.json import jsonify from flask_login import current_user from app.decorators import permission_required from app.entreprises import LOGS_LEN from app.entreprises.forms import ( EntrepriseCreationForm, EntrepriseModificationForm, SuppressionConfirmationForm, OffreCreationForm, OffreModificationForm, CorrespondantCreationForm, CorrespondantModificationForm, ContactCreationForm, ContactModificationForm, StageApprentissageCreationForm, StageApprentissageModificationForm, EnvoiOffreForm, AjoutFichierForm, ValidationConfirmationForm, ImportForm, PreferencesForm, ) from app.entreprises import bp from app.entreprises.models import ( Entreprise, EntrepriseOffre, EntrepriseCorrespondant, EntrepriseLog, EntrepriseContact, EntrepriseStageApprentissage, EntrepriseEnvoiOffre, EntrepriseOffreDepartement, EntreprisePreferences, ) from app.entreprises import app_relations_entreprises as are from app.models import Identite from app.auth.models import User from app.scodoc.sco_permissions import Permission from app.scodoc import sco_etud, sco_excel import app.scodoc.sco_utils as scu from app import db from sqlalchemy import text from werkzeug.utils import secure_filename @bp.route("/", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) def index(): """ Permet d'afficher une page avec la liste des entreprises (visible) et une liste des dernières opérations """ entreprises = Entreprise.query.filter_by(visible=True) logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all() return render_template( "entreprises/entreprises.html", title="Entreprises", entreprises=entreprises, logs=logs, ) @bp.route("/logs", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) def logs(): """ Permet d'afficher les logs (toutes les entreprises) """ page = request.args.get("page", 1, type=int) logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).paginate( page=page, per_page=20 ) return render_template( "entreprises/logs.html", title="Logs", logs=logs, ) @bp.route("/validation", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesValidate) def validation(): """ Permet d'afficher une page avec la liste des entreprises a valider (non visible) """ entreprises = Entreprise.query.filter_by(visible=False).all() return render_template( "entreprises/entreprises_validation.html", title="Validation entreprises", entreprises=entreprises, ) @bp.route("/correspondants", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) def correspondants(): """ Permet d'afficher une page avec la liste des correspondants des entreprises visibles et une liste des dernières opérations """ correspondants = ( db.session.query(EntrepriseCorrespondant, Entreprise) .join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id) .filter_by(visible=True) ) logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all() return render_template( "entreprises/correspondants.html", title="Correspondants", correspondants=correspondants, logs=logs, ) @bp.route("/fiche_entreprise/", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) def fiche_entreprise(id): """ Permet d'afficher la fiche entreprise d'une entreprise avec une liste des dernières opérations et l'historique des étudiants ayant réaliser un stage ou une alternance dans cette entreprise. La fiche entreprise comporte les informations de l'entreprise, les correspondants de l'entreprise et les offres de l'entreprise. """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"fiche entreprise {id} inconnue" ) offres_with_files = [] depts = are.get_depts() for offre in entreprise.offres: if not offre.expired and ( offre.expiration_date is None or ( offre.expiration_date is not None and date.today() < offre.expiration_date ) ): offre_with_files = are.get_offre_files_and_depts(offre, depts) if offre_with_files is not None: offres_with_files.append(offre_with_files) correspondants = entreprise.correspondants[:] logs = ( EntrepriseLog.query.order_by(EntrepriseLog.date.desc()) .filter_by(object=id) .limit(LOGS_LEN) .all() ) stages_apprentissages = ( db.session.query(EntrepriseStageApprentissage, Identite) .order_by(EntrepriseStageApprentissage.date_debut.desc()) .filter(EntrepriseStageApprentissage.entreprise_id == id) .join(Identite, Identite.id == EntrepriseStageApprentissage.etudid) .all() ) return render_template( "entreprises/fiche_entreprise.html", title="Fiche entreprise", entreprise=entreprise, correspondants=correspondants, offres=offres_with_files, logs=logs, stages_apprentissages=stages_apprentissages, ) @bp.route("/logs/", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) def logs_entreprise(id): """ Permet d'afficher les logs d'une entreprise """ page = request.args.get("page", 1, type=int) entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"logs fiche entreprise {id} inconnu" ) logs = ( EntrepriseLog.query.order_by(EntrepriseLog.date.desc()) .filter_by(object=id) .paginate(page=page, per_page=20) ) return render_template( "entreprises/logs_entreprise.html", title="Logs", logs=logs, entreprise=entreprise, ) @bp.route("/fiche_entreprise_validation/", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesValidate) def fiche_entreprise_validation(id): """ Permet d'afficher la fiche entreprise d'une entreprise a valider """ entreprise = Entreprise.query.filter_by(id=id, visible=False).first_or_404( description=f"fiche entreprise (validation) {id} inconnue" ) correspondants = entreprise.correspondants return render_template( "entreprises/fiche_entreprise_validation.html", title="Validation fiche entreprise", entreprise=entreprise, correspondants=correspondants, ) @bp.route("/offres_recues", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) def offres_recues(): """ Permet d'afficher la page où l'on peut voir les offres reçues """ offres_recues = ( db.session.query(EntrepriseEnvoiOffre, EntrepriseOffre) .filter(EntrepriseEnvoiOffre.receiver_id == current_user.id) .join(EntrepriseOffre, EntrepriseOffre.id == EntrepriseEnvoiOffre.offre_id) .all() ) offres_recues_with_files = [] for offre in offres_recues: correspondant = EntrepriseCorrespondant.query.filter_by( id=offre[1].correspondant_id ).first() files = [] path = os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{offre[1].entreprise_id}", f"{offre[1].id}", ) if os.path.exists(path): for dir in glob.glob( f"{path}/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]" ): for file in glob.glob(f"{dir}/*"): file = [os.path.basename(dir), os.path.basename(file)] files.append(file) offres_recues_with_files.append([offre[0], offre[1], files, correspondant]) return render_template( "entreprises/offres_recues.html", title="Offres reçues", offres_recues=offres_recues_with_files, ) @bp.route("/fiche_entreprise//offres_expirees") @permission_required(Permission.RelationsEntreprisesView) def offres_expirees(id): """ Permet d'afficher la liste des offres expirés d'une entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"fiche entreprise {id} inconnue" ) offres_expirees_with_files = [] depts = are.get_depts() for offre in entreprise.offres: if offre.expired or ( offre.expiration_date is not None and date.today() > offre.expiration_date ): offre_expiree_with_files = are.get_offre_files_and_depts(offre, depts) if offre_expiree_with_files is not None: offres_expirees_with_files.append(offre_expiree_with_files) return render_template( "entreprises/offres_expirees.html", title="Offres expirées", entreprise=entreprise, offres_expirees=offres_expirees_with_files, ) @bp.route("/add_entreprise", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def add_entreprise(): """ Permet d'ajouter une entreprise dans la base avec un formulaire """ form = EntrepriseCreationForm() if form.validate_on_submit(): entreprise = Entreprise( nom=form.nom_entreprise.data.strip(), siret=form.siret.data.strip(), adresse=form.adresse.data.strip(), codepostal=form.codepostal.data.strip(), ville=form.ville.data.strip(), pays=form.pays.data.strip() if form.pays.data.strip() else "FRANCE", ) db.session.add(entreprise) db.session.commit() db.session.refresh(entreprise) correspondant = EntrepriseCorrespondant( entreprise_id=entreprise.id, nom=form.nom_correspondant.data.strip(), prenom=form.prenom_correspondant.data.strip(), telephone=form.telephone.data.strip(), mail=form.mail.data.strip(), poste=form.poste.data.strip(), service=form.service.data.strip(), ) db.session.add(correspondant) if current_user.has_permission(Permission.RelationsEntreprisesValidate, None): entreprise.visible = True nom_entreprise = f"{entreprise.nom}" log = EntrepriseLog( authenticated_user=current_user.user_name, text=f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom}) avec un correspondant", ) db.session.add(log) db.session.commit() flash("L'entreprise a été ajouté à la liste.") return redirect(url_for("entreprises.index")) else: entreprise.visible = False db.session.commit() if EntreprisePreferences.get_email_notifications(): are.send_email_notifications_entreprise( "entreprise en attente de validation", entreprise, correspondant ) flash("L'entreprise a été ajouté à la liste pour la validation.") return redirect(url_for("entreprises.index")) return render_template( "entreprises/ajout_entreprise.html", title="Ajout entreprise avec correspondant", form=form, ) @bp.route("/edit_entreprise/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def edit_entreprise(id): """ Permet de modifier une entreprise de la base avec un formulaire """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) form = EntrepriseModificationForm(hidden_entreprise_siret=entreprise.siret) if form.validate_on_submit(): nom_entreprise = f"{form.nom.data.strip()}" if entreprise.nom != form.nom.data.strip(): log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text=f"{nom_entreprise} - Modification du nom (ancien nom: {entreprise.nom})", ) entreprise.nom = form.nom.data.strip() db.session.add(log) if entreprise.adresse != form.adresse.data.strip(): log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text=f"{nom_entreprise} - Modification de l'adresse (ancienne adresse: {entreprise.adresse})", ) entreprise.adresse = form.adresse.data.strip() db.session.add(log) if entreprise.codepostal != form.codepostal.data.strip(): log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text=f"{nom_entreprise} - Modification du code postal (ancien code postal: {entreprise.codepostal})", ) entreprise.codepostal = form.codepostal.data.strip() db.session.add(log) if entreprise.ville != form.ville.data.strip(): log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text=f"{nom_entreprise} - Modification de la ville (ancienne ville: {entreprise.ville})", ) entreprise.ville = form.ville.data.strip() db.session.add(log) if entreprise.pays != form.pays.data.strip() or not form.pays.data.strip(): log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text=f"{nom_entreprise} - Modification du pays (ancien pays: {entreprise.pays})", ) entreprise.pays = ( form.pays.data.strip() if form.pays.data.strip() else "FRANCE" ) db.session.add(log) db.session.commit() flash("L'entreprise a été modifié.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) elif request.method == "GET": form.siret.data = entreprise.siret form.nom.data = entreprise.nom form.adresse.data = entreprise.adresse form.codepostal.data = entreprise.codepostal form.ville.data = entreprise.ville form.pays.data = entreprise.pays return render_template( "entreprises/form_modification_entreprise.html", title="Modification entreprise", form=form, ) @bp.route("/delete_entreprise/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def delete_entreprise(id): """ Permet de supprimer une entreprise de la base avec un formulaire de confirmation """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) form = SuppressionConfirmationForm() if form.validate_on_submit(): db.session.delete(entreprise) # supprime les fichiers attachés aux offres path = os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{entreprise.id}", ) if os.path.isdir(path): shutil.rmtree(path) log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text=f"Suppression de la fiche entreprise ({entreprise.nom})", ) db.session.add(log) db.session.commit() flash("L'entreprise a été supprimé de la liste.") return redirect(url_for("entreprises.index")) return render_template( "entreprises/delete_confirmation.html", title="Supression entreprise", form=form, ) @bp.route("/validate_entreprise/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesValidate) def validate_entreprise(id): """ Permet de valider une entreprise """ form = ValidationConfirmationForm() entreprise = Entreprise.query.filter_by(id=id, visible=False).first_or_404( description=f"entreprise (validation) {id} inconnue" ) if form.validate_on_submit(): entreprise.visible = True nom_entreprise = f"{entreprise.nom}" log = EntrepriseLog( authenticated_user=current_user.user_name, text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom}) avec un correspondant", ) db.session.add(log) db.session.commit() flash("L'entreprise a été validé et ajouté à la liste.") return redirect(url_for("entreprises.index")) return render_template( "entreprises/validate_confirmation.html", title="Validation entreprise", form=form, ) @bp.route("/delete_validation_entreprise/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesValidate) def delete_validation_entreprise(id): """ Permet de supprimer une entreprise en attente de validation avec une formulaire de validation """ entreprise = Entreprise.query.filter_by(id=id, visible=False).first_or_404( description=f"entreprise (validation) {id} inconnue" ) form = SuppressionConfirmationForm() if form.validate_on_submit(): db.session.delete(entreprise) db.session.commit() flash("L'entreprise a été supprimé de la liste des entreprise à valider.") return redirect(url_for("entreprises.validation")) return render_template( "entreprises/delete_confirmation.html", title="Supression entreprise", form=form, ) @bp.route("/add_offre/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def add_offre(id): """ Permet d'ajouter une offre a une entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) form = OffreCreationForm(hidden_entreprise_id=id) if form.validate_on_submit(): offre = EntrepriseOffre( entreprise_id=entreprise.id, intitule=form.intitule.data.strip(), description=form.description.data.strip(), type_offre=form.type_offre.data.strip(), missions=form.missions.data.strip(), duree=form.duree.data.strip(), expiration_date=form.expiration_date.data, correspondant_id=form.correspondant.data, ) db.session.add(offre) db.session.commit() db.session.refresh(offre) for dept in form.depts.data: offre_dept = EntrepriseOffreDepartement( offre_id=offre.id, dept_id=dept, ) db.session.add(offre_dept) log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text="Création d'une offre", ) db.session.add(log) db.session.commit() flash("L'offre a été ajouté à la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return render_template( "entreprises/form.html", title="Ajout offre", form=form, ) @bp.route("/edit_offre/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def edit_offre(id): """ Permet de modifier une offre """ offre = EntrepriseOffre.query.filter_by(id=id).first_or_404( description=f"offre {id} inconnue" ) offre_depts = EntrepriseOffreDepartement.query.filter_by(offre_id=offre.id).all() form = OffreModificationForm( hidden_entreprise_id=offre.entreprise_id, correspondant=offre.correspondant_id ) offre_depts_list = [(offre_dept.dept_id) for offre_dept in offre_depts] if form.validate_on_submit(): offre.intitule = form.intitule.data.strip() offre.description = form.description.data.strip() offre.type_offre = form.type_offre.data.strip() offre.missions = form.missions.data.strip() offre.duree = form.duree.data.strip() offre.expiration_date = form.expiration_date.data offre.correspondant_id = form.correspondant.data if offre_depts_list != form.depts.data: for dept in form.depts.data: if dept not in offre_depts_list: offre_dept = EntrepriseOffreDepartement( offre_id=offre.id, dept_id=dept, ) db.session.add(offre_dept) for dept in offre_depts_list: if dept not in form.depts.data: offre_dept = EntrepriseOffreDepartement.query.filter_by( offre_id=offre.id, dept_id=dept ).first_or_404() db.session.delete(offre_dept) log = EntrepriseLog( authenticated_user=current_user.user_name, object=offre.entreprise_id, text="Modification d'une offre", ) db.session.add(log) db.session.commit() flash("L'offre a été modifié.") return redirect(url_for("entreprises.fiche_entreprise", id=offre.entreprise.id)) elif request.method == "GET": form.intitule.data = offre.intitule form.description.data = offre.description form.type_offre.data = offre.type_offre form.missions.data = offre.missions form.duree.data = offre.duree form.expiration_date.data = offre.expiration_date form.depts.data = offre_depts_list return render_template( "entreprises/form.html", title="Modification offre", form=form, ) @bp.route("/delete_offre/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def delete_offre(id): """ Permet de supprimer une offre """ offre = EntrepriseOffre.query.filter_by(id=id).first_or_404( description=f"offre {id} inconnue" ) entreprise_id = offre.entreprise.id form = SuppressionConfirmationForm() if form.validate_on_submit(): db.session.delete(offre) path = os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{entreprise_id}", f"{offre.id}", ) if os.path.isdir(path): shutil.rmtree(path) log = EntrepriseLog( authenticated_user=current_user.user_name, object=offre.entreprise_id, text="Suppression d'une offre", ) db.session.add(log) db.session.commit() flash("L'offre a été supprimé de la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise_id)) return render_template( "entreprises/delete_confirmation.html", title="Supression offre", form=form, ) @bp.route("/delete_offre_recue/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesView) def delete_offre_recue(id): """ Permet de supprimer une offre reçue """ offre_recue = EntrepriseEnvoiOffre.query.filter_by( id=id, receiver_id=current_user.id ).first_or_404(description=f"offre recu {id} inconnue") db.session.delete(offre_recue) db.session.commit() return redirect(url_for("entreprises.offres_recues")) @bp.route("/expired/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def expired(id): """ Permet de rendre expirée et non expirée une offre """ offre = EntrepriseOffre.query.filter_by(id=id).first_or_404( description=f"offre {id} inconnue" ) offre.expired = not offre.expired db.session.commit() if offre.expired: flash("L'offre a été rendu expirée") else: flash("L'offre a été rendu non expirée") return redirect(url_for("entreprises.fiche_entreprise", id=offre.entreprise_id)) @bp.route("/add_correspondant/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def add_correspondant(id): """ Permet d'ajouter un correspondant a une entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) form = CorrespondantCreationForm(hidden_entreprise_id=entreprise.id) if form.validate_on_submit(): correspondant = EntrepriseCorrespondant( entreprise_id=entreprise.id, nom=form.nom.data.strip(), prenom=form.prenom.data.strip(), telephone=form.telephone.data.strip(), mail=form.mail.data.strip(), poste=form.poste.data.strip(), service=form.service.data.strip(), ) log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, text="Création d'un correspondant", ) db.session.add(log) db.session.add(correspondant) db.session.commit() flash("Le correspondant a été ajouté à la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return render_template( "entreprises/form.html", title="Ajout correspondant", form=form, ) @bp.route("/edit_correspondant/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def edit_correspondant(id): """ Permet de modifier un correspondant """ correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404( description=f"correspondant {id} inconnu" ) form = CorrespondantModificationForm( hidden_entreprise_id=correspondant.entreprise_id, hidden_correspondant_id=correspondant.id, ) if form.validate_on_submit(): correspondant.nom = form.nom.data.strip() correspondant.prenom = form.prenom.data.strip() correspondant.telephone = form.telephone.data.strip() correspondant.mail = form.mail.data.strip() correspondant.poste = form.poste.data.strip() correspondant.service = form.service.data.strip() log = EntrepriseLog( authenticated_user=current_user.user_name, object=correspondant.entreprise_id, text="Modification d'un correspondant", ) db.session.add(log) db.session.commit() flash("Le correspondant a été modifié.") return redirect( url_for("entreprises.fiche_entreprise", id=correspondant.entreprise.id) ) elif request.method == "GET": form.nom.data = correspondant.nom form.prenom.data = correspondant.prenom form.telephone.data = correspondant.telephone form.mail.data = correspondant.mail form.poste.data = correspondant.poste form.service.data = correspondant.service return render_template( "entreprises/form.html", title="Modification correspondant", form=form, ) @bp.route("/delete_correspondant/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def delete_correspondant(id): """ Permet de supprimer un correspondant """ correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404( description=f"correspondant {id} inconnu" ) form = SuppressionConfirmationForm() if form.validate_on_submit(): correspondant_count = EntrepriseCorrespondant.query.filter_by( entreprise_id=correspondant.entreprise_id ).count() if correspondant_count == 1: flash( "Le correspondant n'a pas été supprimé de la fiche entreprise. (1 correspondant minimum)" ) return redirect( url_for("entreprises.fiche_entreprise", id=correspondant.entreprise_id) ) else: db.session.delete(correspondant) log = EntrepriseLog( authenticated_user=current_user.user_name, object=correspondant.entreprise_id, text="Suppression d'un correspondant", ) db.session.add(log) db.session.commit() flash("Le correspondant a été supprimé de la fiche entreprise.") return redirect( url_for("entreprises.fiche_entreprise", id=correspondant.entreprise_id) ) return render_template( "entreprises/delete_confirmation.html", title="Supression correspondant", form=form, ) @bp.route("fiche_entreprise/add_contact/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def add_contact(id): """ Permet d'ajouter un contact avec une entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) form = ContactCreationForm() if form.validate_on_submit(): contact = EntrepriseContact( date=form.date.data, user=current_user.id, # a voir entreprise=entreprise.id, notes=form.notes.data.strip(), ) db.session.add(contact) db.session.commit() return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return render_template( "entreprises/form.html", title="Ajout contact", form=form, ) @bp.route("fiche_entreprise/edit_contact/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def edit_contact(id): """ Permet d'editer un contact avec une entreprise """ contact = EntrepriseContact.query.filter_by(id=id).first_or_404( description=f"contact {id} inconnu" ) form = ContactModificationForm() if form.validate_on_submit(): contact.date = form.date.data contact.notes = form.notes.data db.session.commit() return redirect(url_for("entreprises.fiche_entreprise", id=contact.entreprise)) elif request.method == "GET": form.date.data = contact.date form.notes.data = contact.notes return render_template( "entreprises/form.html", title="Modification contact", form=form, ) @bp.route("/fiche_entreprise/contacts/") def contacts(id): contacts = EntrepriseContact.query.filter_by(entreprise=id).all() return render_template( "entreprises/contacts.html", title="Liste des contacts", contacts=contacts, entreprise_id=id, ) @bp.route("/add_stage_apprentissage/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def add_stage_apprentissage(id): """ Permet d'ajouter un étudiant ayant réalisé un stage ou une alternance sur la fiche entreprise de l'entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) form = StageApprentissageCreationForm() if form.validate_on_submit(): etudiant_nomcomplet = form.etudiant.data.upper().strip() stm = text( "SELECT id, CONCAT(nom, ' ', prenom) as nom_prenom FROM Identite WHERE CONCAT(nom, ' ', prenom)=:nom_prenom" ) etudiant = ( Identite.query.from_statement(stm) .params(nom_prenom=etudiant_nomcomplet) .first() ) formation = etudiant.inscription_courante_date( form.date_debut.data, form.date_fin.data ) stage_apprentissage = EntrepriseStageApprentissage( entreprise_id=entreprise.id, etudid=etudiant.id, type_offre=form.type_offre.data.strip(), date_debut=form.date_debut.data, date_fin=form.date_fin.data, formation_text=formation.formsemestre.titre if formation else None, formation_scodoc=formation.formsemestre.formsemestre_id if formation else None, notes=form.notes.data.strip(), ) db.session.add(stage_apprentissage) db.session.commit() flash("L'étudiant a été ajouté sur la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return render_template( "entreprises/ajout_stage_apprentissage.html", title="Ajout stage / apprentissage", form=form, ) @bp.route("/edit_stage_apprentissage/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def edit_stage_apprentissage(id): """ Permet de modifier un étudiant ayant réalisé un stage ou une alternance sur la fiche entreprise de l'entreprise """ stage_apprentissage = EntrepriseStageApprentissage.query.filter_by( id=id ).first_or_404(description=f"stage_apprentissage {id} inconnue") etudiant = Identite.query.filter_by(id=stage_apprentissage.etudid).first_or_404( description=f"etudiant {id} inconnue" ) form = StageApprentissageModificationForm() if form.validate_on_submit(): etudiant_nomcomplet = form.etudiant.data.upper().strip() stm = text( "SELECT id, CONCAT(nom, ' ', prenom) as nom_prenom FROM Identite WHERE CONCAT(nom, ' ', prenom)=:nom_prenom" ) etudiant = ( Identite.query.from_statement(stm) .params(nom_prenom=etudiant_nomcomplet) .first() ) formation = etudiant.inscription_courante_date( form.date_debut.data, form.date_fin.data ) stage_apprentissage.etudid = etudiant.id stage_apprentissage.type_offre = form.type_offre.data.strip() stage_apprentissage.date_debut = form.date_debut.data stage_apprentissage.date_fin = form.date_fin.data stage_apprentissage.formation_text = ( formation.formsemestre.titre if formation else None, ) stage_apprentissage.formation_scodoc = ( formation.formsemestre.formsemestre_id if formation else None, ) stage_apprentissage.notes = form.notes.data.strip() db.session.commit() return redirect( url_for( "entreprises.fiche_entreprise", id=stage_apprentissage.entreprise_id ) ) elif request.method == "GET": form.etudiant.data = f"{sco_etud.format_nom(etudiant.nom)} {sco_etud.format_prenom(etudiant.prenom)}" form.type_offre.data = stage_apprentissage.type_offre form.date_debut.data = stage_apprentissage.date_debut form.date_fin.data = stage_apprentissage.date_fin form.notes.data = stage_apprentissage.notes return render_template( "entreprises/ajout_stage_apprentissage.html", title="Modification stage / apprentissage", form=form, ) @bp.route("/delete_stage_apprentissage/", methods=["GET", "POST"]) def delete_stage_apprentissage(id): """ Permet de supprimer un étudiant ayant réalisé un stage ou une alternance sur la fiche entreprise de l'entreprise """ stage_apprentissage = EntrepriseStageApprentissage.query.filter_by( id=id ).first_or_404(description=f"stage_apprentissage {id} inconnu") form = SuppressionConfirmationForm() if form.validate_on_submit(): db.session.delete(stage_apprentissage) db.session.commit() return redirect( url_for( "entreprises.fiche_entreprise", id=stage_apprentissage.entreprise_id ) ) return render_template( "entreprises/delete_confirmation.html", title="Supression stage/apprentissage", form=form, ) @bp.route("/envoyer_offre/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesSend) def envoyer_offre(id): """ Permet d'envoyer une offre à un utilisateur ScoDoc """ offre = EntrepriseOffre.query.filter_by(id=id).first_or_404( description=f"offre {id} inconnue" ) form = EnvoiOffreForm() if form.validate_on_submit(): for field in form: if ( field.name in ["responsable_1", "responsable_2", "responsable_3"] and field.data ): responsable_data = field.data.upper().strip() stm = text( "SELECT id, UPPER(CONCAT(nom, ' ', prenom, ' ', '(', user_name, ')')) FROM \"user\" WHERE UPPER(CONCAT(nom, ' ', prenom, ' ', '(', user_name, ')'))=:responsable_data" ) responsable = ( User.query.from_statement(stm) .params(responsable_data=responsable_data) .first() ) envoi_offre = EntrepriseEnvoiOffre( sender_id=current_user.id, receiver_id=responsable.id, offre_id=offre.id, ) db.session.add(envoi_offre) flash(f"L'offre a été envoyé à {responsable.get_nomplogin()}.") db.session.commit() return redirect(url_for("entreprises.fiche_entreprise", id=offre.entreprise_id)) return render_template( "entreprises/envoi_offre_form.html", title="Envoyer une offre", form=form, ) @bp.route("/etudiants") @permission_required(Permission.RelationsEntreprisesChange) def json_etudiants(): """ Permet de récuperer un JSON avec tous les étudiants """ if request.args.get("term") is None: abort(400) term = request.args.get("term").strip() etudiants = Identite.query.filter(Identite.nom.ilike(f"%{term}%")).all() list = [] for etudiant in etudiants: content = {} value = f"{sco_etud.format_nom(etudiant.nom)} {sco_etud.format_prenom(etudiant.prenom)}" if etudiant.inscription_courante() is not None: content = { "id": f"{etudiant.id}", "value": value, "info": f"{etudiant.inscription_courante().formsemestre.titre}", } else: content = {"id": f"{etudiant.id}", "value": value} list.append(content) return jsonify(results=list) @bp.route("/responsables") @permission_required(Permission.RelationsEntreprisesChange) def json_responsables(): """ Permet de récuperer un JSON avec tous les utilisateurs ScoDoc """ if request.args.get("term") is None: abort(400) term = request.args.get("term").strip() responsables = User.query.filter( User.nom.ilike(f"%{term}%"), User.nom.is_not(None), User.prenom.is_not(None) ).all() list = [] for responsable in responsables: content = {} value = f"{responsable.get_nomplogin()}" content = {"id": f"{responsable.id}", "value": value, "info": ""} list.append(content) return jsonify(results=list) @bp.route("/export_entreprises") @permission_required(Permission.RelationsEntreprisesExport) def export_entreprises(): """ Permet d'exporter la liste des entreprises sous format excel (.xlsx) """ entreprises = Entreprise.query.filter_by(visible=True).all() if entreprises: keys = ["siret", "nom_entreprise", "adresse", "ville", "code_postal", "pays"] titles = keys[:] L = [ [entreprise.to_dict().get(k, "") for k in keys] for entreprise in entreprises ] title = "Entreprises" xlsx = sco_excel.excel_simple_table(titles=titles, lines=L, sheet_name=title) filename = title return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE) else: abort(404) @bp.route("/get_import_entreprises_file_sample") @permission_required(Permission.RelationsEntreprisesExport) def get_import_entreprises_file_sample(): """ Permet de récupérer un fichier exemple vide pour pouvoir importer des entreprises """ keys = [ "siret", "nom_entreprise", "adresse", "ville", "code_postal", "pays", ] titles = keys[:] title = "ImportEntreprises" xlsx = sco_excel.excel_simple_table(titles=titles, sheet_name="Entreprises") filename = title return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE) @bp.route("/import_entreprises", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesExport) def import_entreprises(): """ Permet d'importer des entreprises a l'aide d'un fichier excel (.xlsx) """ form = ImportForm() if form.validate_on_submit(): file = form.fichier.data file_path = os.path.join( Config.SCODOC_VAR_DIR, "tmp", secure_filename(file.filename) ) file.save(file_path) data = sco_excel.excel_file_to_list(file_path) os.remove(file_path) entreprises_import = [] siret_list = [] ligne = 0 titles = ["siret", "nom_entreprise", "adresse", "ville", "code_postal", "pays"] if data[1][0] != titles: flash("Veuillez utilisez la feuille excel à remplir") return render_template( "entreprises/import_entreprises.html", title="Importation entreprises", form=form, ) for entreprise_data in data[1][1:]: ligne += 1 if ( are.verif_entreprise_data(entreprise_data) and entreprise_data[0] not in siret_list ): siret_list.append(entreprise_data[0]) entreprise = Entreprise( siret=entreprise_data[0], nom=entreprise_data[1], adresse=entreprise_data[2], ville=entreprise_data[3], codepostal=entreprise_data[4], pays=entreprise_data[5], visible=True, ) entreprises_import.append(entreprise) else: flash(f"Erreur lors de l'importation (ligne {ligne})") return render_template( "entreprises/import_entreprises.html", title="Importation entreprises", form=form, ) if len(entreprises_import) > 0: for entreprise in entreprises_import: db.session.add(entreprise) log = EntrepriseLog( authenticated_user=current_user.user_name, text=f"Importation de {len(entreprises_import)} entreprise(s)", ) db.session.add(log) db.session.commit() flash(f"Importation réussie de {len(entreprises_import)} entreprise(s)") return render_template( "entreprises/import_entreprises.html", title="Importation entreprises", form=form, entreprises_import=entreprises_import, ) else: flash('Feuille "Entreprises" vide') return render_template( "entreprises/import_entreprises.html", title="Importation entreprises", form=form, ) @bp.route("/export_correspondants") @permission_required(Permission.RelationsEntreprisesExport) def export_correspondants(): """ Permet d'exporter la liste des correspondants sous format excel (.xlsx) """ correspondants = ( db.session.query(EntrepriseCorrespondant) .join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id) .filter_by(visible=True) .all() ) if correspondants: keys = [ "nom", "prenom", "telephone", "mail", "poste", "service", "entreprise_siret", ] titles = keys[:] L = [ [correspondant.to_dict().get(k, "") for k in keys] for correspondant in correspondants ] title = "Correspondants" xlsx = sco_excel.excel_simple_table(titles=titles, lines=L, sheet_name=title) filename = title return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE) else: abort(404) @bp.route("/get_import_correspondants_file_sample") @permission_required(Permission.RelationsEntreprisesExport) def get_import_correspondants_file_sample(): """ Permet de récupérer un fichier exemple vide pour pouvoir importer des correspondants """ keys = [ "nom", "prenom", "telephone", "mail", "poste", "service", "entreprise_siret", ] titles = keys[:] title = "ImportCorrespondants" xlsx = sco_excel.excel_simple_table(titles=titles, sheet_name="Correspondants") filename = title return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE) @bp.route("/import_correspondants", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesExport) def import_correspondants(): """ Permet d'importer des correspondants a l'aide d'un fichier excel (.xlsx) """ form = ImportForm() if form.validate_on_submit(): file = form.fichier.data file_path = os.path.join( Config.SCODOC_VAR_DIR, "tmp", secure_filename(file.filename) ) file.save(file_path) data = sco_excel.excel_file_to_list(file_path) os.remove(file_path) correspondants_import = [] correspondant_list = [] ligne = 0 titles = [ "nom", "prenom", "telephone", "mail", "poste", "service", "entreprise_siret", ] if data[1][0] != titles: flash("Veuillez utilisez la feuille excel à remplir") return render_template( "entreprises/import_correspondants.html", title="Importation correspondants", form=form, ) for correspondant_data in data[1][1:]: ligne += 1 if ( are.verif_correspondant_data(correspondant_data) and ( correspondant_data[0], correspondant_data[1], correspondant_data[6], ) not in correspondant_list ): correspondant_list.append( ( correspondant_data[0], correspondant_data[1], correspondant_data[6], ) ) entreprise = Entreprise.query.filter_by( siret=correspondant_data[6] ).first() correspondant = EntrepriseCorrespondant( nom=correspondant_data[0], prenom=correspondant_data[1], telephone=correspondant_data[2], mail=correspondant_data[3], poste=correspondant_data[4], service=correspondant_data[5], entreprise_id=entreprise.id, ) correspondants_import.append(correspondant) else: flash(f"Erreur lors de l'importation (ligne {ligne})") return render_template( "entreprises/import_correspondants.html", title="Importation correspondants", form=form, ) if len(correspondants_import) > 0: for correspondant in correspondants_import: db.session.add(correspondant) log = EntrepriseLog( authenticated_user=current_user.user_name, text=f"Importation de {len(correspondants_import)} correspondant(s)", ) db.session.add(log) db.session.commit() flash( f"Importation réussie de {len(correspondants_import)} correspondant(s)" ) return render_template( "entreprises/import_correspondants.html", title="Importation correspondants", form=form, correspondants_import=correspondants_import, ) else: flash('Feuille "Correspondants" vide') return render_template( "entreprises/import_correspondants.html", title="Importation correspondants", form=form, ) @bp.route( "/get_offre_file////" ) @permission_required(Permission.RelationsEntreprisesView) def get_offre_file(entreprise_id, offre_id, filedir, filename): """ Permet de télécharger un fichier d'une offre """ if os.path.isfile( os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{entreprise_id}", f"{offre_id}", f"{filedir}", f"{filename}", ) ): return send_file( os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{entreprise_id}", f"{offre_id}", f"{filedir}", f"{filename}", ), as_attachment=True, ) else: abort(404, description=f"fichier {filename} inconnu") @bp.route("/add_offre_file/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def add_offre_file(offre_id): """ Permet d'ajouter un fichier à une offre """ offre = EntrepriseOffre.query.filter_by(id=offre_id).first_or_404( description=f"offre {offre_id} inconnue" ) form = AjoutFichierForm() if form.validate_on_submit(): date = f"{datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}" path = os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{offre.entreprise_id}", f"{offre.id}", f"{date}", ) os.makedirs(path) file = form.fichier.data filename = secure_filename(file.filename) file.save(os.path.join(path, filename)) flash("Le fichier a été ajouté a l'offre.") return redirect(url_for("entreprises.fiche_entreprise", id=offre.entreprise_id)) return render_template( "entreprises/form.html", title="Ajout fichier à une offre", form=form, ) @bp.route("/delete_offre_file//", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) def delete_offre_file(offre_id, filedir): """ Permet de supprimer un fichier d'une offre """ offre = EntrepriseOffre.query.filter_by(id=offre_id).first_or_404( description=f"offre {offre_id} inconnue" ) form = SuppressionConfirmationForm() if form.validate_on_submit(): path = os.path.join( Config.SCODOC_VAR_DIR, "entreprises", f"{offre.entreprise_id}", f"{offre_id}", f"{filedir}", ) if os.path.isdir(path): shutil.rmtree(path) flash("Le fichier relié à l'offre a été supprimé.") return redirect( url_for("entreprises.fiche_entreprise", id=offre.entreprise_id) ) return render_template( "entreprises/delete_confirmation.html", title="Suppression fichier d'une offre", form=form, ) @bp.route("/preferences", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesValidate) def preferences(): """ Permet d'afficher la page des préférences du module gestion des relations entreprises """ form = PreferencesForm() if form.validate_on_submit(): EntreprisePreferences.set_email_notifications(form.mail_entreprise.data.strip()) EntreprisePreferences.set_check_siret(int(form.check_siret.data)) return redirect(url_for("entreprises.index")) elif request.method == "GET": form.mail_entreprise.data = EntreprisePreferences.get_email_notifications() form.check_siret.data = int(EntreprisePreferences.get_check_siret()) return render_template( "entreprises/preferences.html", title="Préférences", form=form, )