applications relations entreprises

This commit is contained in:
Arthur ZHU 2021-12-23 19:28:25 +01:00
parent 2d2b2b2f39
commit 30eb738c25
17 changed files with 965 additions and 76 deletions

View File

@ -199,6 +199,10 @@ def create_app(config_class=DevConfig):
app.register_blueprint(auth_bp, url_prefix="/auth")
from app.entreprises import bp as entreprises_bp
app.register_blueprint(entreprises_bp, url_prefix="/ScoDoc/entreprises")
from app.views import scodoc_bp
from app.views import scolar_bp
from app.views import notes_bp

View File

@ -0,0 +1,25 @@
"""entreprises.__init__
"""
from flask import Blueprint
from app.scodoc import sco_etud
from app.auth.models import User
bp = Blueprint("entreprises", __name__)
LOGS_LEN = 10
@bp.app_template_filter()
def format_prenom(s):
return sco_etud.format_prenom(s)
@bp.app_template_filter()
def format_nom(s):
return sco_etud.format_nom(s)
@bp.app_template_filter()
def get_nomcomplet(s):
user = User.query.filter_by(user_name=s).first()
return user.get_nomcomplet();
from app.entreprises import routes

120
app/entreprises/forms.py Normal file
View File

@ -0,0 +1,120 @@
from flask import flash
from markupsafe import Markup
from flask.app import Flask
import requests, re
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField, SelectField, FileField
from wtforms.fields.html5 import EmailField, DateField
from wtforms.validators import ValidationError, DataRequired, Email
from app.entreprises.models import Entreprise
from app.models import Identite
from app.auth.models import User
from app.scodoc import sco_etud
from sqlalchemy import text
DATA_REQUIRED_ERROR_MESSAGE = "Ce champ est requis"
class EntrepriseCreationForm(FlaskForm):
siret = StringField("SIRET", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)], render_kw={"placeholder": "Numéro composé de 14 chiffres"})
nom_entreprise = StringField("Nom de l'entreprise", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
adresse = StringField("Adresse de l'entreprise", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
codepostal = StringField("Code postal de l'entreprise", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
ville = StringField("Ville de l'entreprise", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
pays = StringField("Pays de l'entreprise", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
nom_contact = StringField("Nom du contact", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
prenom_contact = StringField("Prénom du contact", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
telephone = StringField("Téléphone du contact", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
mail = EmailField("Mail du contact", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE), Email(message="Adresse e-mail invalide")])
submit = SubmitField("Envoyer")
def validate_siret(self, siret):
siret = siret.data.strip()
if re.match("^\d{14}$", siret) == None:
raise ValidationError("Format incorrect")
req = requests.get(f"https://entreprise.data.gouv.fr/api/sirene/v1/siret/{siret}")
if req.status_code != 200:
raise ValidationError("SIRET inexistant")
entreprise = Entreprise.query.filter_by(siret=siret).first()
if entreprise is not None:
lien = f"<a href=\"/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}\">ici</a>"
raise ValidationError(Markup(f"Entreprise déjà présent, lien vers la fiche : {lien}"))
class EntrepriseModificationForm(FlaskForm):
siret = StringField("SIRET", validators=[], render_kw={"disabled":""})
nom = StringField("Nom de l'entreprise", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
adresse = StringField("Adresse", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
codepostal = StringField("Code postal", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
ville = StringField("Ville", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
pays = StringField("Pays", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
submit = SubmitField("Modifier")
class OffreCreationForm(FlaskForm):
intitule = StringField("Intitulé", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
description = TextAreaField("Description", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
type_offre = SelectField("Type de l'offre", choices=[('Stage'), ('Alternance')], validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
missions = TextAreaField("Missions", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
duree = StringField("Durée", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
ficher = FileField("Fichier", validators=[])
submit = SubmitField("Envoyer")
class OffreModificationForm(FlaskForm):
intitule = StringField("Intitulé", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
description = TextAreaField("Description", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
type_offre = SelectField("Type de l'offre", choices=[('Stage'), ('Alternance')], validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
missions = TextAreaField("Missions", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
duree = StringField("Durée", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
submit = SubmitField("Modifier")
class ContactCreationForm(FlaskForm):
nom = StringField("Nom", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
prenom = StringField("Prénom", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
telephone = StringField("Téléphone", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
mail = EmailField("Mail", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE), Email(message="Adresse e-mail invalide")])
submit = SubmitField("Envoyer")
class ContactModificationForm(FlaskForm):
nom = StringField("Nom", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
prenom = StringField("Prénom", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
telephone = StringField("Téléphone", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
mail = EmailField("Mail", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE), Email(message="Adresse e-mail invalide")])
submit = SubmitField("Modifier")
class HistoriqueCreationForm(FlaskForm):
etudiant = StringField("Étudiant", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)], render_kw={"placeholder": "Tapez le nom de l'étudiant puis selectionnez"})
type_offre = SelectField("Type de l'offre", choices=[('Stage'), ('Alternance')], validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
date_debut = DateField("Date début", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
date_fin = DateField("Date fin", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
submit = SubmitField("Envoyer")
def validate(self):
rv = FlaskForm.validate(self)
if not rv:
return False
if self.date_debut.data > self.date_fin.data:
self.date_debut.errors.append("Les dates sont incompatibles")
self.date_fin.errors.append("Les dates sont incompatibles")
return False
return True
def validate_etudiant(self, etudiant):
etudiant_data = 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_data).first()
if etudiant is None:
raise ValidationError("Champ incorrect (selectionnez dans la liste)")
class EnvoiOffreForm(FlaskForm):
responsable = StringField("Responsable de formation", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
submit = SubmitField("Envoyer")
def validate_responsable(self, responsable):
responsable_data = responsable.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()
if responsable is None:
raise ValidationError("Champ incorrect (selectionnez dans la liste)")
class SuppressionConfirmationForm(FlaskForm):
submit = SubmitField("Supprimer")

52
app/entreprises/models.py Normal file
View File

@ -0,0 +1,52 @@
from app import db
class Entreprise(db.Model):
__tablename__ = "entreprises"
id = db.Column(db.Integer, primary_key=True)
siret = db.Column(db.Text)
nom = db.Column(db.Text)
adresse = db.Column(db.Text)
codepostal = db.Column(db.Text)
ville = db.Column(db.Text)
pays = db.Column(db.Text)
contacts = db.relationship('EntrepriseContact', backref='entreprise', lazy='dynamic')
offres = db.relationship('EntrepriseOffre', backref='entreprise', lazy='dynamic')
class EntrepriseContact(db.Model):
__tablename__ = "entreprise_contact"
id = db.Column(db.Integer, primary_key=True)
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
nom = db.Column(db.Text)
prenom = db.Column(db.Text)
telephone = db.Column(db.Text)
mail = db.Column(db.Text)
class EntrepriseOffre(db.Model):
__tablename__ = "entreprise_offre"
id = db.Column(db.Integer, primary_key=True)
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
date_ajout = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
intitule = db.Column(db.Text)
description = db.Column(db.Text)
type_offre = db.Column(db.Text)
missions = db.Column(db.Text)
duree = db.Column(db.Text)
class EntrepriseLog(db.Model):
__tablename__ = "entreprise_log"
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
authenticated_user = db.Column(db.Text)
object = db.Column(db.Integer)
text = db.Column(db.Text)
class EntrepriseHistory(db.Model):
__tablename__ = "entreprise_history"
id = db.Column(db.Integer, primary_key=True)
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
etudid = db.Column(db.Integer)
type_offre = db.Column(db.Text)
date_debut = db.Column(db.Date)
date_fin = db.Column(db.Date)
formation_text = db.Column(db.Text)
formation_scodoc = db.Column(db.Integer)

374
app/entreprises/routes.py Normal file
View File

@ -0,0 +1,374 @@
from flask import render_template, redirect, url_for, request, flash
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.scodoc.sco_permissions import Permission
from app.entreprises.forms import (
EntrepriseCreationForm,
EntrepriseModificationForm,
SuppressionConfirmationForm,
OffreCreationForm,
OffreModificationForm,
ContactCreationForm,
ContactModificationForm,
HistoriqueCreationForm,
EnvoiOffreForm
)
from app.entreprises import bp
from app.entreprises.models import (
Entreprise,
EntrepriseOffre,
EntrepriseContact,
EntrepriseLog,
EntrepriseHistory
)
from app.models import (
Identite
)
from app.auth.models import User
from app.scodoc.sco_find_etud import search_etud_by_name
from app import db
from app.scodoc import sco_etud
from sqlalchemy import text
@bp.route("/", methods=["GET", "POST"])
def index():
entreprises = Entreprise.query.all()
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("/add_entreprise", methods=["GET", "POST"])
def add_entreprise():
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()
)
db.session.add(entreprise)
db.session.commit()
db.session.refresh(entreprise)
contact = EntrepriseContact(
entreprise_id=entreprise.id,
nom=form.nom_contact.data.strip(),
prenom=form.prenom_contact.data.strip(),
telephone=form.telephone.data.strip(),
mail=form.mail.data.strip()
)
db.session.add(contact)
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>"
log = EntrepriseLog(
authenticated_user = current_user.user_name,
text = f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom}) avec un contact",
)
db.session.add(log)
db.session.commit()
flash("L'entreprise a été ajouté à la liste.")
return redirect(url_for("entreprises.index"))
return render_template("entreprises/form.html", title=("Ajout entreprise + contact"), form=form)
@bp.route("/edit_entreprise/<id>", methods=["GET", "POST"])
def edit_entreprise(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
form = EntrepriseModificationForm()
if form.validate_on_submit():
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{form.nom.data.strip()}</a>"
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():
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()
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.html", title=("Modification entreprise"), form=form)
@bp.route("/delete_entreprise/<id>", methods=["GET", "POST"])
def delete_entreprise(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
form = SuppressionConfirmationForm()
if form.validate_on_submit():
db.session.delete(entreprise)
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("/fiche_entreprise/<id>", methods=["GET", "POST"])
def fiche_entreprise(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
offres = entreprise.offres
contacts = entreprise.contacts
logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).filter_by(object=id).limit(LOGS_LEN).all()
historique = db.session.query(EntrepriseHistory, Identite).order_by(EntrepriseHistory.date_debut.desc()).\
filter_by(entreprise_id=id).\
join(Identite, Identite.id == EntrepriseHistory.etudid).all()
return render_template("entreprises/fiche_entreprise.html", title=("Fiche entreprise"), entreprise=entreprise, contacts=contacts, offres=offres, logs=logs, historique=historique)
@bp.route("/add_offre/<id>", methods=["GET", "POST"])
def add_offre(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
form = OffreCreationForm()
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()
)
log = EntrepriseLog(
authenticated_user = current_user.user_name,
object = entreprise.id,
text = "Création d'une offre",
)
db.session.add(log)
db.session.add(offre)
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/<id>", methods=["GET", "POST"])
def edit_offre(id):
offre = EntrepriseOffre.query.filter_by(id=id).first_or_404()
form = OffreModificationForm()
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()
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
return render_template("entreprises/form.html", title=("Modification offre"), form=form)
@bp.route("/delete_offre/<id>", methods=["GET", "POST"])
def delete_offre(id):
offre = EntrepriseOffre.query.filter_by(id=id).first_or_404()
entreprise_id = offre.entreprise.id
form = SuppressionConfirmationForm()
if form.validate_on_submit():
db.session.delete(offre)
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("/add_contact/<id>", methods=["GET", "POST"])
def add_contact(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
form = ContactCreationForm()
if form.validate_on_submit():
contact = EntrepriseContact(
entreprise_id=entreprise.id,
nom=form.nom.data.strip(),
prenom=form.prenom.data.strip(),
telephone=form.telephone.data.strip(),
mail=form.mail.data.strip()
)
log = EntrepriseLog(
authenticated_user = current_user.user_name,
object = entreprise.id,
text = "Création d'un contact",
)
db.session.add(log)
db.session.add(contact)
db.session.commit()
flash("Le contact a été ajouté à la fiche entreprise.")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
return render_template("entreprises/form.html", title=("Ajout contact"), form=form)
@bp.route("/edit_contact/<id>", methods=["GET", "POST"])
def edit_contact(id):
contact = EntrepriseContact.query.filter_by(id=id).first_or_404()
form = ContactModificationForm()
if form.validate_on_submit():
contact.nom = form.nom.data.strip()
contact.prenom = form.prenom.data.strip()
contact.telephone = form.telephone.data.strip()
contact.mail = form.mail.data.strip()
log = EntrepriseLog(
authenticated_user = current_user.user_name,
object = contact.entreprise_id,
text = "Modification d'un contact",
)
db.session.add(log)
db.session.commit()
flash("Le contact a été modifié.")
return redirect(url_for("entreprises.fiche_entreprise", id=contact.entreprise.id))
elif request.method == 'GET':
form.nom.data = contact.nom
form.prenom.data = contact.prenom
form.telephone.data = contact.telephone
form.mail.data = contact.mail
return render_template("entreprises/form.html", title=("Modification contact"), form=form)
@bp.route("/delete_contact/<id>", methods=["GET", "POST"])
def delete_contact(id):
contact = EntrepriseContact.query.filter_by(id=id).first_or_404()
entreprise_id = contact.entreprise.id
form = SuppressionConfirmationForm()
if form.validate_on_submit():
contact_count = EntrepriseContact.query.filter_by(entreprise_id=contact.entreprise.id).count()
if contact_count == 1:
flash("Le contact n'a pas été supprimé de la fiche entreprise. (1 contact minimum)")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise_id))
else:
db.session.delete(contact)
log = EntrepriseLog(
authenticated_user = current_user.user_name,
object = contact.entreprise_id,
text = "Suppression d'un contact",
)
db.session.add(log)
db.session.commit()
flash("Le contact 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 contact"), form=form)
@bp.route("/add_historique/<id>", methods=["GET", "POST"])
def add_historique(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
form = HistoriqueCreationForm()
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)
historique = EntrepriseHistory(
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
)
db.session.add(historique)
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/form.html", title=("Ajout historique"), form=form)
@bp.route("/etudiants")
def json_etudiants():
term = request.args.get('term').strip()
etudiants = Identite.query.filter(Identite.nom.ilike(f"%{term}%")).all()
list = []
content = {}
for etudiant in etudiants:
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)
content = {}
return jsonify(results=list)
@bp.route("/envoyer_offre/<id>", methods=["GET", "POST"])
def envoyer_offre(id):
form = EnvoiOffreForm()
if form.validate_on_submit():
print("tmp") # faire l'envoie du mail
return render_template("entreprises/form.html", title=("Envoyer une offre"), form=form)
@bp.route("/responsables")
def json_responsables():
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 = []
content = {}
for responsable in responsables:
value = f"{responsable.get_nomplogin()}"
content = {
"id": f"{responsable.id}",
"value": value,
"info": ""
}
list.append(content)
content = {}
return jsonify(results=list)

View File

@ -14,12 +14,6 @@ from app.models.raw_sql_init import create_database_functions
from app.models.absences import Absence, AbsenceNotification, BilletAbsence
from app.models.departements import Departement
from app.models.entreprises import (
Entreprise,
EntrepriseCorrespondant,
EntrepriseContact,
)
from app.models.etudiants import (
Identite,
Adresse,

View File

@ -19,7 +19,7 @@ class Departement(db.Model):
db.Boolean(), nullable=False, default=True, server_default="true"
) # sur page d'accueil
entreprises = db.relationship("Entreprise", lazy="dynamic", backref="departement")
# entreprises = db.relationship("Entreprise", lazy="dynamic", backref="departement")
etudiants = db.relationship("Identite", lazy="dynamic", backref="departement")
formations = db.relationship("Formation", lazy="dynamic", backref="departement")
formsemestres = db.relationship(

View File

@ -1,69 +0,0 @@
# -*- coding: UTF-8 -*
"""Gestion des absences
"""
from app import db
from app.models import APO_CODE_STR_LEN
from app.models import SHORT_STR_LEN
from app.models import CODE_STR_LEN
class Entreprise(db.Model):
"""une entreprise"""
__tablename__ = "entreprises"
id = db.Column(db.Integer, primary_key=True)
entreprise_id = db.synonym("id")
dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True)
nom = db.Column(db.Text)
adresse = db.Column(db.Text)
ville = db.Column(db.Text)
codepostal = db.Column(db.Text)
pays = db.Column(db.Text)
contact_origine = db.Column(db.Text)
secteur = db.Column(db.Text)
note = db.Column(db.Text)
privee = db.Column(db.Text)
localisation = db.Column(db.Text)
# -1 inconnue, 0, 25, 50, 75, 100:
qualite_relation = db.Column(db.Integer)
plus10salaries = db.Column(db.Boolean())
date_creation = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
class EntrepriseCorrespondant(db.Model):
"""Personne contact en entreprise"""
__tablename__ = "entreprise_correspondant"
id = db.Column(db.Integer, primary_key=True)
entreprise_corresp_id = db.synonym("id")
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
nom = db.Column(db.Text)
prenom = db.Column(db.Text)
civilite = db.Column(db.Text)
fonction = db.Column(db.Text)
phone1 = db.Column(db.Text)
phone2 = db.Column(db.Text)
mobile = db.Column(db.Text)
mail1 = db.Column(db.Text)
mail2 = db.Column(db.Text)
fax = db.Column(db.Text)
note = db.Column(db.Text)
class EntrepriseContact(db.Model):
"""Evènement (contact) avec une entreprise"""
__tablename__ = "entreprise_contact"
id = db.Column(db.Integer, primary_key=True)
entreprise_contact_id = db.synonym("id")
date = db.Column(db.DateTime(timezone=True))
type_contact = db.Column(db.Text)
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
entreprise_corresp_id = db.Column(
db.Integer, db.ForeignKey("entreprise_correspondant.id")
)
etudid = db.Column(db.Integer) # sans contrainte pour garder logs après suppression
description = db.Column(db.Text)
enseignant = db.Column(db.Text)

View File

@ -107,6 +107,14 @@ class Identite(db.Model):
]
return r[0] if r else None
def inscription_courante_date(self, date_debut, date_fin):
r = [
ins
for ins in self.formsemestre_inscriptions
if ins.formsemestre.est_courant_date(date_debut, date_fin)
]
return r[0] if r else None
def etat_inscription(self, formsemestre_id):
"""etat de l'inscription de cet étudiant au semestre:
False si pas inscrit, ou scu.INSCRIT, DEMISSION, DEF

View File

@ -146,6 +146,12 @@ class FormSemestre(db.Model):
today = datetime.date.today()
return (self.date_debut <= today) and (today <= self.date_fin)
def est_courant_date(self, date_debut, date_fin) -> bool:
"""Vrai si la date actuelle (now) est dans le semestre
(les dates de début et fin sont incluses)
"""
return (self.date_debut <= date_debut) and (date_fin <= self.date_fin)
def est_decale(self):
"""Vrai si semestre "décalé"
c'est à dire semestres impairs commençant entre janvier et juin

View File

@ -0,0 +1,13 @@
<div>
<p>
Nom : {{ contact.nom }}<br>
Prénom : {{ contact.prenom }}<br>
Téléphone : {{ contact.telephone }}<br>
Mail : {{ contact.mail }}<br>
</p>
<div style="margin-bottom: 10px;">
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_contact', id=contact.id) }}">Modifier contact</a>
<a class="btn btn-danger" href="{{ url_for('entreprises.delete_contact', id=contact.id) }}">Supprimer contact</a>
</div>
</div>

View File

@ -0,0 +1,15 @@
<div>
<p>
Intitulé : {{ offre.intitule }}<br>
Description : {{ offre.description }}<br>
Type de l'offre : {{ offre.type_offre }}<br>
Missions : {{ offre.missions }}<br>
Durée : {{ offre.duree }}<br>
</p>
<div style="margin-bottom: 10px;">
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_offre', id=offre.id) }}">Modifier l'offre</a>
<a class="btn btn-danger" href="{{ url_for('entreprises.delete_offre', id=offre.id) }}">Supprimer l'offre</a>
<a class="btn btn-primary" href="{{ url_for('entreprises.envoyer_offre', id=offre.id) }}">Envoyer l'offre</a>
</div>
</div>

View File

@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>{{ title }}</h1>
<br>
<div style="color:red">Cliquez sur le bouton supprimer pour confirmer votre supression</div>
<br>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,65 @@
{% extends 'base.html' %}
{% block app_content %}
<!-- <style>
#entreprises-table {
table-layout: fixed;
width: 100%;
word-wrap: break-word;
}
</style> -->
{% if logs %}
<div class="container">
<h3>Dernières opérations</h3>
<ul>
{% for log in logs %}
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet }}</span></li>
{% endfor %}
</ul>
</div>
{% endif %}
<div class="container">
<h1>Liste des entreprises</h1>
{% if entreprises %}
<div class="table-responsive">
<table id="entreprises-table" class="table table-bordered table-hover">
<tr>
<th>SIRET</th>
<th>Nom</th>
<th>Adresse</th>
<th>Code postal</th>
<th>Ville</th>
<th>Pays</th>
<th>Action</th>
</tr>
{% for entreprise in entreprises %}
<tr class="table-row active">
<th><a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}">{{ entreprise.siret }}</a></th>
<th class="entreprise-nom">{{ entreprise.nom }}</th>
<th>{{ entreprise.adresse }}</th>
<th>{{ entreprise.codepostal }}</th>
<th>{{ entreprise.ville }}</th>
<th>{{ entreprise.pays }}</th>
<th>
<div class="btn-group">
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="{{ url_for('entreprises.edit_entreprise', id=entreprise.id) }}">Modifier</a></li>
<li><a href="{{ url_for('entreprises.delete_entreprise', id=entreprise.id) }}" style="color:red">Supprimer</a></li>
</ul>
</div>
</th>
</tr>
{% endfor %}
</table>
<br>
{% else %}
<div>Aucune entreprise présent dans la base</div>
<br>
</div>
{% endif %}
<a class="btn btn-default" href="{{ url_for('entreprises.add_entreprise') }}">Ajouter une entreprise</a>
</div>
{% endblock %}

View File

@ -0,0 +1,70 @@
{% extends 'base.html' %}
{% block app_content %}
{% if logs %}
<div class="container">
<h3>Dernières opérations sur cette fiche</h3>
<ul>
{% for log in logs %}
<li>
<span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span>
<span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet }}</span>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if historique %}
<div class="container">
<h3>Historique</h3>
<ul>
{% for data in historique %}
<li>
<span style="margin-right: 10px;">{{ data[0].date_debut.strftime('%d/%m/%Y') }} - {{ data[0].date_fin.strftime('%d/%m/%Y') }}</span>
<span style="margin-right: 10px;">{{ data[0].type_offre }} réalisé par {{ data[1].nom|format_nom }} {{ data[1].prenom|format_prenom }}</span>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
<div class="container">
<h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2>
<div>
<p>
SIRET : {{ entreprise.siret }}<br>
Nom : {{ entreprise.nom }}<br>
Adresse : {{ entreprise.adresse }}<br>
Code postal : {{ entreprise.codepostal }}<br>
Ville : {{ entreprise.ville }}<br>
Pays : {{ entreprise.pays }}
</p>
</div>
{% if contacts %}
<div>
{% for contact in contacts %}
Contact {{loop.index}}
{% include 'entreprises/_contact.html' %}
{% endfor %}
</div>
{% endif %}
{% if offres %}
<div>
{% for offre in offres %}
Offre {{loop.index}} (ajouté le {{offre.date_ajout.strftime('%d/%m/%Y') }})
{% include 'entreprises/_offre.html' %}
{% endfor %}
</div>
{% endif %}
<div>
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_entreprise', id=entreprise.id) }}">Modifier</a>
<a class="btn btn-danger" href="{{ url_for('entreprises.delete_entreprise', id=entreprise.id) }}">Supprimer</a>
<a class="btn btn-primary" href="{{ url_for('entreprises.add_offre', id=entreprise.id) }}">Ajouter offre</a>
<a class="btn btn-primary" href="{{ url_for('entreprises.add_contact', id=entreprise.id) }}">Ajouter contact</a>
<a class="btn btn-primary" href="{{ url_for('entreprises.add_historique', id=entreprise.id) }}">Ajouter historique</a>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,71 @@
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block styles %}
{{super()}}
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
{% endblock %}
{% block app_content %}
<h1>{{ title }}</h1>
<br>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form, novalidate=True) }}
</div>
</div>
<script>
window.onload = function(e){
var etudiants_options = {
script: "/ScoDoc/entreprises/etudiants?",
varname: "term",
json: true,
noresults: "Valeur invalide !",
minchars: 2,
timeout: 60000
};
var as_etudiants = new bsn.AutoSuggest('etudiant', etudiants_options);
var responsables_options = {
script: "/ScoDoc/entreprises/responsables?",
varname: "term",
json: true,
noresults: "Valeur invalide !",
minchars: 2,
timeout: 60000
};
var as_responsables = new bsn.AutoSuggest('responsable', responsables_options);
document.getElementById("siret").addEventListener("keyup", autocomplete);
function autocomplete() {
var input = document.getElementById("siret").value;
data = null
if(input.length == 14) {
fetch("https://entreprise.data.gouv.fr/api/sirene/v1/siret/" + input)
.then(response => {
if(response.ok)
return response.json()
else {
document.getElementById("nom_entreprise").value = ''
document.getElementById("adresse").value = ''
document.getElementById("codepostal").value = ''
document.getElementById("ville").value = ''
document.getElementById("pays").value = ''
throw new Error("404")
}
})
.then(function(response) {
data = JSON.parse(JSON.stringify(response))
document.getElementById("nom_entreprise").value = data.etablissement.l1_normalisee
document.getElementById("adresse").value = data.etablissement.l4_normalisee
document.getElementById("codepostal").value = data.etablissement.code_postal
document.getElementById("ville").value = data.etablissement.libelle_commune
document.getElementById("pays").value = 'France'
})
.catch(err => err)
}
}
}
</script>
{% endblock %}

View File

@ -0,0 +1,127 @@
"""creation tables relations entreprises
Revision ID: f62d3a0bde1a
Revises: 39818df276aa
Create Date: 2021-12-10 11:25:04.135491
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'f62d3a0bde1a'
down_revision = '91be8a06d423'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('entreprise_log',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('date', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.Column('authenticated_user', sa.Text(), nullable=True),
sa.Column('object', sa.Integer(), nullable=True),
sa.Column('text', sa.Text(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_table('entreprise_history',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('entreprise_id', sa.Integer(), nullable=True),
sa.Column('etudid', sa.Integer(), nullable=True),
sa.Column('type_offre', sa.Text(), nullable=True),
sa.Column('date_debut', sa.Date(), nullable=True),
sa.Column('date_fin', sa.Date(), nullable=True),
sa.Column('formation_text', sa.Text(), nullable=True),
sa.Column('formation_scodoc', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['entreprise_id'], ['entreprises.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_table('entreprise_offre',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('entreprise_id', sa.Integer(), nullable=True),
sa.Column('date_ajout', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.Column('intitule', sa.Text(), nullable=True),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('type_offre', sa.Text(), nullable=True),
sa.Column('missions', sa.Text(), nullable=True),
sa.Column('duree', sa.Text(), nullable=True),
sa.ForeignKeyConstraint(['entreprise_id'], ['entreprises.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.drop_constraint('entreprise_contact_entreprise_corresp_id_fkey', 'entreprise_contact', type_='foreignkey')
op.drop_table('entreprise_correspondant')
op.add_column('entreprise_contact', sa.Column('nom', sa.Text(), nullable=True))
op.add_column('entreprise_contact', sa.Column('prenom', sa.Text(), nullable=True))
op.add_column('entreprise_contact', sa.Column('telephone', sa.Text(), nullable=True))
op.add_column('entreprise_contact', sa.Column('mail', sa.Text(), nullable=True))
op.drop_column('entreprise_contact', 'date')
op.drop_column('entreprise_contact', 'description')
op.drop_column('entreprise_contact', 'type_contact')
op.drop_column('entreprise_contact', 'enseignant')
op.drop_column('entreprise_contact', 'entreprise_corresp_id')
op.drop_column('entreprise_contact', 'etudid')
op.add_column('entreprises', sa.Column('siret', sa.Text(), nullable=True))
op.drop_index('ix_entreprises_dept_id', table_name='entreprises')
op.drop_constraint('entreprises_dept_id_fkey', 'entreprises', type_='foreignkey')
op.drop_column('entreprises', 'localisation')
op.drop_column('entreprises', 'contact_origine')
op.drop_column('entreprises', 'qualite_relation')
op.drop_column('entreprises', 'secteur')
op.drop_column('entreprises', 'plus10salaries')
op.drop_column('entreprises', 'dept_id')
op.drop_column('entreprises', 'privee')
op.drop_column('entreprises', 'date_creation')
op.drop_column('entreprises', 'note')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('entreprises', sa.Column('note', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('date_creation', postgresql.TIMESTAMP(timezone=True), server_default=sa.text('now()'), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('privee', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('dept_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('plus10salaries', sa.BOOLEAN(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('secteur', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('qualite_relation', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('contact_origine', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('localisation', sa.TEXT(), autoincrement=False, nullable=True))
op.create_foreign_key('entreprises_dept_id_fkey', 'entreprises', 'departement', ['dept_id'], ['id'])
op.create_index('ix_entreprises_dept_id', 'entreprises', ['dept_id'], unique=False)
op.drop_column('entreprises', 'siret')
op.add_column('entreprise_contact', sa.Column('etudid', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('entreprise_contact', sa.Column('entreprise_corresp_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('entreprise_contact', sa.Column('enseignant', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprise_contact', sa.Column('type_contact', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprise_contact', sa.Column('description', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprise_contact', sa.Column('date', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True))
op.create_table('entreprise_correspondant',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('entreprise_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('nom', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('prenom', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('civilite', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('fonction', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('phone1', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('phone2', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('mobile', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('mail1', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('mail2', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('fax', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('note', sa.TEXT(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['entreprise_id'], ['entreprises.id'], name='entreprise_correspondant_entreprise_id_fkey'),
sa.PrimaryKeyConstraint('id', name='entreprise_correspondant_pkey')
)
op.create_foreign_key('entreprise_contact_entreprise_corresp_id_fkey', 'entreprise_contact', 'entreprise_correspondant', ['entreprise_corresp_id'], ['id'])
op.drop_column('entreprise_contact', 'mail')
op.drop_column('entreprise_contact', 'telephone')
op.drop_column('entreprise_contact', 'prenom')
op.drop_column('entreprise_contact', 'nom')
op.drop_table('entreprise_offre')
op.drop_table('entreprise_history')
op.drop_table('entreprise_log')
# ### end Alembic commands ###