Compare commits

...

5 Commits

9 changed files with 218 additions and 98 deletions

View File

@ -3,10 +3,10 @@ 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 import StringField, SubmitField, TextAreaField, SelectField, FileField, HiddenField
from wtforms.fields.html5 import EmailField, DateField
from wtforms.validators import ValidationError, DataRequired, Email
from app.entreprises.models import Entreprise
from app.entreprises.models import Entreprise, EntrepriseContact
from app.models import Identite
from app.auth.models import User
from app.scodoc import sco_etud
@ -71,8 +71,27 @@ class ContactCreationForm(FlaskForm):
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")])
hidden_entreprise_id = HiddenField()
submit = SubmitField("Envoyer")
def validate(self):
rv = FlaskForm.validate(self)
if not rv:
return False
contact = EntrepriseContact.query.filter_by(
entreprise_id = self.hidden_entreprise_id.data,
nom = self.nom.data,
prenom = self.prenom.data
).first()
if contact is not None:
self.nom.errors.append("Ce contact existe déjà (même nom et prénom)")
self.prenom.errors.append("")
return False
return True
class ContactModificationForm(FlaskForm):
nom = StringField("Nom", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])
prenom = StringField("Prénom", validators=[DataRequired(message=DATA_REQUIRED_ERROR_MESSAGE)])

View File

@ -20,6 +20,8 @@ class EntrepriseContact(db.Model):
prenom = db.Column(db.Text)
telephone = db.Column(db.Text)
mail = db.Column(db.Text)
poste = db.Column(db.Text)
service = db.Column(db.Text)
class EntrepriseOffre(db.Model):
__tablename__ = "entreprise_offre"
@ -40,8 +42,8 @@ class EntrepriseLog(db.Model):
object = db.Column(db.Integer)
text = db.Column(db.Text)
class EntrepriseHistory(db.Model):
__tablename__ = "entreprise_history"
class EntrepriseEtudiant(db.Model):
__tablename__ = "entreprise_etudiant"
id = db.Column(db.Integer, primary_key=True)
entreprise_id = db.Column(db.Integer, db.ForeignKey("entreprises.id"))
etudid = db.Column(db.Integer)
@ -50,3 +52,10 @@ class EntrepriseHistory(db.Model):
date_fin = db.Column(db.Date)
formation_text = db.Column(db.Text)
formation_scodoc = db.Column(db.Integer)
class EntrepriseEnvoiOffre(db.Model):
__tablename__ = "entreprise_envoi_offre"
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
offre_id = db.Column(db.Integer, db.ForeignKey("entreprise_offre.id"))
date_envoi = db.Column(db.DateTime(timezone=True), server_default=db.func.now())

View File

@ -21,7 +21,7 @@ from app.entreprises.models import (
EntrepriseOffre,
EntrepriseContact,
EntrepriseLog,
EntrepriseHistory
EntrepriseEtudiant
)
from app.models import (
Identite
@ -51,9 +51,9 @@ def fiche_entreprise(id):
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()).\
historique = db.session.query(EntrepriseEtudiant, Identite).order_by(EntrepriseEtudiant.date_debut.desc()).\
filter_by(entreprise_id=id).\
join(Identite, Identite.id == EntrepriseHistory.etudid).all()
join(Identite, Identite.id == EntrepriseEtudiant.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_entreprise", methods=["GET", "POST"])
@ -88,7 +88,7 @@ def add_entreprise():
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)
return render_template("entreprises/ajout_entreprise.html", title=("Ajout entreprise + contact"), form=form)
@bp.route("/edit_entreprise/<id>", methods=["GET", "POST"])
def edit_entreprise(id):
@ -238,7 +238,7 @@ def delete_offre(id):
@bp.route("/add_contact/<id>", methods=["GET", "POST"])
def add_contact(id):
entreprise = Entreprise.query.filter_by(id=id).first_or_404()
form = ContactCreationForm()
form = ContactCreationForm(hidden_entreprise_id=entreprise.id)
if form.validate_on_submit():
contact = EntrepriseContact(
entreprise_id=entreprise.id,
@ -316,7 +316,7 @@ def add_historique(id):
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(
historique = EntrepriseEtudiant(
entreprise_id = entreprise.id,
etudid = etudiant.id,
type_offre = form.type_offre.data.strip(),
@ -331,14 +331,14 @@ def add_historique(id):
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)
return render_template("entreprises/ajout_historique.html", title=("Ajout historique"), form=form)
@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)
return render_template("entreprises/envoi_offre_form.html", title=("Envoyer une offre"), form=form)
@bp.route("/etudiants")
def json_etudiants():

View File

@ -0,0 +1,59 @@
{% 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">
<p>
Les champs s'autocomplète selon le SIRET
</p>
{{ wtf.quick_form(form, novalidate=True) }}
</div>
</div>
<script>
window.onload = function(e){
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 {
emptyForm()
}
})
.then(response => fillForm(response))
.catch(err => err)
}
}
function fillForm(response) {
document.getElementById("nom_entreprise").value = response.etablissement.l1_normalisee
document.getElementById("adresse").value = response.etablissement.l4_normalisee
document.getElementById("codepostal").value = response.etablissement.code_postal
document.getElementById("ville").value = response.etablissement.libelle_commune
document.getElementById("pays").value = 'FRANCE'
}
function emptyForm() {
document.getElementById("nom_entreprise").value = ''
document.getElementById("adresse").value = ''
document.getElementById("codepostal").value = ''
document.getElementById("ville").value = ''
document.getElementById("pays").value = ''
}
}
</script>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% 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);
}
</script>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% 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 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);
}
</script>
{% endblock %}

View File

@ -15,61 +15,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 {
emptyForm()
}
})
.then(response => fillForm(response))
.catch(err => err)
}
}
function fillForm(response) {
document.getElementById("nom_entreprise").value = response.etablissement.l1_normalisee
document.getElementById("adresse").value = response.etablissement.l4_normalisee
document.getElementById("codepostal").value = response.etablissement.code_postal
document.getElementById("ville").value = response.etablissement.libelle_commune
document.getElementById("pays").value = 'FRANCE'
}
function emptyForm() {
document.getElementById("nom_entreprise").value = ''
document.getElementById("adresse").value = ''
document.getElementById("codepostal").value = ''
document.getElementById("ville").value = ''
document.getElementById("pays").value = ''
}
}
</script>
{% endblock %}

View File

@ -1,8 +1,8 @@
"""creation tables relations entreprises
Revision ID: f62d3a0bde1a
Revises: 39818df276aa
Create Date: 2021-12-10 11:25:04.135491
Revision ID: f3b62d64efa3
Revises: 91be8a06d423
Create Date: 2021-12-24 10:36:27.150085
"""
from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = 'f62d3a0bde1a'
revision = 'f3b62d64efa3'
down_revision = '91be8a06d423'
branch_labels = None
depends_on = None
@ -26,7 +26,8 @@ def upgrade():
sa.Column('text', sa.Text(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_table('entreprise_history',
op.create_table('entreprise_etudiant',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('entreprise_id', sa.Integer(), nullable=True),
sa.Column('etudid', sa.Integer(), nullable=True),
@ -38,6 +39,7 @@ def upgrade():
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),
@ -51,53 +53,66 @@ def upgrade():
sa.PrimaryKeyConstraint('id')
)
op.create_table('entreprise_envoi_offre',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('offre_id', sa.Integer(), nullable=True),
sa.Column('date_envoi', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True),
sa.ForeignKeyConstraint(['offre_id'], ['entreprise_offre.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.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.add_column('entreprise_contact', sa.Column('poste', sa.Text(), nullable=True))
op.add_column('entreprise_contact', sa.Column('service', sa.Text(), nullable=True))
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', 'date')
op.drop_column('entreprise_contact', 'type_contact')
op.drop_column('entreprise_contact', 'etudid')
op.drop_column('entreprise_contact', 'entreprise_corresp_id')
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')
op.drop_column('entreprises', 'contact_origine')
op.drop_column('entreprises', 'plus10salaries')
op.drop_column('entreprises', 'privee')
op.drop_column('entreprises', 'secteur')
op.drop_column('entreprises', 'date_creation')
op.drop_column('entreprises', 'dept_id')
op.drop_column('entreprises', 'localisation')
# ### 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.add_column('entreprises', sa.Column('dept_id', sa.INTEGER(), 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('secteur', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('privee', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('plus10salaries', sa.BOOLEAN(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('contact_origine', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('note', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprises', sa.Column('qualite_relation', sa.INTEGER(), 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('etudid', sa.INTEGER(), 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.add_column('entreprise_contact', sa.Column('enseignant', sa.TEXT(), autoincrement=False, nullable=True))
op.add_column('entreprise_contact', sa.Column('description', sa.TEXT(), 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),
@ -116,12 +131,15 @@ def downgrade():
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', 'service')
op.drop_column('entreprise_contact', 'poste')
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_envoi_offre')
op.drop_table('entreprise_offre')
op.drop_table('entreprise_history')
op.drop_table('entreprise_etudiant')
op.drop_table('entreprise_log')
# ### end Alembic commands ###
# ### end Alembic commands ###

View File

@ -248,6 +248,16 @@ def edit_role(rolename, addpermissionname=None, removepermissionname=None): # e
db.session.add(role)
db.session.commit()
@app.cli.command()
@click.argument("rolename")
def delete_role(rolename):
"""Delete a role"""
role = Role.query.filter_by(name=rolename).first()
if role is None:
sys.stderr.write(f"delete_role: role {rolename} does not exists\n")
return 1
db.session.delete(role)
db.session.commit()
@app.cli.command()
@click.argument("username")