Compare commits

..

No commits in common. "0db3acf2719ed4f1c1a27c0d298273884e688753" and "989930e4ce94c9d93771dcc737197d2df43d0383" have entirely different histories.

30 changed files with 666 additions and 1590 deletions

3
.gitignore vendored
View File

@ -173,6 +173,3 @@ Thumbs.db
.idea/ .idea/
copy copy
# Symlinks static ScoDoc
app/static/links/[0-9]*.*[0-9]

View File

@ -153,4 +153,4 @@ def liste_semestres_courant(dept_ident: str):
FormSemestre.date_fin >= app.db.func.now(), FormSemestre.date_fin >= app.db.func.now(),
) )
return jsonify([d.to_dict(convert_parcours=True) for d in formsemestres]) return jsonify([d.to_dict() for d in formsemestres])

View File

@ -1,7 +1,6 @@
"""entreprises.__init__ """entreprises.__init__
""" """
from datetime import datetime
from flask import Blueprint from flask import Blueprint
from app.scodoc import sco_etud from app.scodoc import sco_etud
from app.auth.models import User from app.auth.models import User
@ -48,12 +47,4 @@ def get_civilité(civ):
return "Madame" return "Madame"
@bp.app_template_filter()
def check_taxe_now(taxes):
for taxe in taxes:
if taxe.annee == int(datetime.now().strftime("%Y")):
return True
return False
from app.entreprises import routes from app.entreprises import routes

View File

@ -30,7 +30,6 @@ import re
import requests import requests
import glob import glob
from flask import flash
from flask_login import current_user from flask_login import current_user
from app.entreprises.models import ( from app.entreprises.models import (
@ -39,61 +38,14 @@ from app.entreprises.models import (
EntrepriseOffre, EntrepriseOffre,
EntrepriseOffreDepartement, EntrepriseOffreDepartement,
EntreprisePreferences, EntreprisePreferences,
EntrepriseSite,
EntrepriseHistorique,
) )
from app import email, db
from app import email
from app.scodoc import sco_preferences from app.scodoc import sco_preferences
from app.scodoc import sco_excel
from app.models import Departement from app.models import Departement
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
ENTREPRISES_KEYS = [
"siret",
"nom_entreprise",
"adresse",
"ville",
"code_postal",
"pays",
]
SITES_KEYS = [
[
"siret_entreprise",
"id_site",
"nom_site",
"adresse",
"ville",
"code_postal",
"pays",
],
[
"civilite",
"nom",
"prenom",
"telephone",
"mail",
"poste",
"service",
"origine",
"notes",
],
]
CORRESPONDANTS_KEYS = [
"id",
"civilite",
"nom",
"prenom",
"telephone",
"mail",
"poste",
"service",
"origine",
"notes",
"nom_site",
]
def get_depts(): def get_depts():
""" """
Retourne une liste contenant les l'id des départements des roles de l'utilisateur courant Retourne une liste contenant les l'id des départements des roles de l'utilisateur courant
@ -106,7 +58,7 @@ def get_depts():
return depts return depts
def get_dept_id_by_acronym(acronym: str): def get_dept_id_by_acronym(acronym):
""" """
Retourne l'id d'un departement a l'aide de son acronym Retourne l'id d'un departement a l'aide de son acronym
""" """
@ -116,14 +68,7 @@ def get_dept_id_by_acronym(acronym: str):
return None return None
def get_dept_acronym_by_id(id: int): def check_offre_depts(depts, offre_depts):
dept = Departement.query.filter_by(id=id).first()
if dept is not None:
return dept.acronym
return None
def check_offre_depts(depts: list, offre_depts: list):
""" """
Retourne vrai si l'utilisateur a le droit de visibilité sur l'offre Retourne vrai si l'utilisateur a le droit de visibilité sur l'offre
""" """
@ -162,7 +107,7 @@ def get_offre_files_and_depts(offre: EntrepriseOffre, depts: list):
return None return None
def send_email_notifications_entreprise(subject: str, entreprise: Entreprise): def send_email_notifications_entreprise(subject, entreprise: Entreprise):
txt = [ txt = [
"Une entreprise est en attente de validation", "Une entreprise est en attente de validation",
"Entreprise:", "Entreprise:",
@ -183,168 +128,69 @@ def send_email_notifications_entreprise(subject: str, entreprise: Entreprise):
return txt return txt
def get_excel_book_are(export: bool = False): def verif_correspondant_data(correspondant_data):
""" """
Retourne un Excel avec les 3 feuilles "Entreprises", "Sites" et "Correspondants" Verifie les données d'une ligne Excel (correspondant)
correspondant_data[0]: civilite
correspondant_data[1]: nom
correspondant_data[2]: prenom
correspondant_data[3]: telephone
correspondant_data[4]: mail
correspondant_data[5]: poste
correspondant_data[6]: service
correspondant_data[7]: origine
correspondant_data[8]: notes
correspondant_data[9]: entreprise_siret
""" """
entreprises_titles = ENTREPRISES_KEYS[:] # champs obligatoires
sites_titles = SITES_KEYS[:] if (
correspondants_titles = CORRESPONDANTS_KEYS[:] correspondant_data[0].strip() == ""
wb = sco_excel.ScoExcelBook() or correspondant_data[1].strip() == ""
ws1 = wb.create_sheet("Entreprises") or correspondant_data[2].strip() == ""
ws1.append_row( or correspondant_data[9].strip() == ""
[ ):
ws1.make_cell(it, style)
for (it, style) in zip(
entreprises_titles,
[sco_excel.excel_make_style(bold=True)] * len(entreprises_titles),
)
]
)
ws2 = wb.create_sheet("Sites")
ws2.append_row(
[
ws2.make_cell(it, style)
for (it, style) in zip(
sites_titles[0],
[sco_excel.excel_make_style(bold=True)] * len(sites_titles[0]),
)
]
+ [
ws2.make_cell(it, style)
for (it, style) in zip(
sites_titles[1],
[sco_excel.excel_make_style(bold=True, color=sco_excel.COLORS.RED)]
* len(sites_titles[1]),
)
]
)
ws3 = wb.create_sheet("Correspondants")
ws3.append_row(
[
ws3.make_cell(it, style)
for (it, style) in zip(
correspondants_titles,
[sco_excel.excel_make_style(bold=True)] * len(correspondants_titles),
)
]
)
if export:
entreprises = Entreprise.query.filter_by(visible=True).all()
sites = (
db.session.query(EntrepriseSite)
.join(Entreprise, EntrepriseSite.entreprise_id == Entreprise.id)
.filter_by(visible=True)
.all()
)
correspondants = (
db.session.query(EntrepriseCorrespondant)
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
.filter_by(visible=True)
.all()
)
entreprises_lines = [
[entreprise.to_dict().get(k, "") for k in ENTREPRISES_KEYS]
for entreprise in entreprises
]
sites_lines = [
[site.to_dict().get(k, "") for k in SITES_KEYS[0]] for site in sites
]
correspondants_lines = [
[correspondant.to_dict().get(k, "") for k in CORRESPONDANTS_KEYS]
for correspondant in correspondants
]
for line in entreprises_lines:
cells = []
for it in line:
cells.append(ws1.make_cell(it))
ws1.append_row(cells)
for line in sites_lines:
cells = []
for it in line:
cells.append(ws2.make_cell(it))
ws2.append_row(cells)
for line in correspondants_lines:
cells = []
for it in line:
cells.append(ws3.make_cell(it))
ws3.append_row(cells)
return wb
def check_entreprises_import(m):
"""
Verifie la feuille Excel "Entreprises" de l'importation données
"""
entreprises_import = []
siret_list = []
ligne = 1
if m[0] != ENTREPRISES_KEYS:
flash(
f'Veuillez utilisez la feuille excel à remplir (Feuille "Entreprises", ligne {ligne})'
)
return False return False
l = list_to_dict(m)
for entreprise_data in l:
ligne += 1
entreprise_data["siret"] = entreprise_data["siret"].replace(" ", "")
if (
check_entreprise_import(entreprise_data)
and entreprise_data["siret"] not in siret_list
):
siret_list.append(entreprise_data["siret"])
entreprise = Entreprise.query.filter_by(
siret=entreprise_data["siret"], visible=True
).first()
if entreprise is None:
entreprise_import = Entreprise(
siret=entreprise_data["siret"],
nom=entreprise_data["nom_entreprise"],
adresse=entreprise_data["adresse"],
ville=entreprise_data["ville"],
codepostal=entreprise_data["code_postal"],
pays=entreprise_data["pays"]
if entreprise_data["pays"]
else "FRANCE",
visible=True,
)
entreprises_import.append(entreprise_import)
else:
entreprise.nom = entreprise_data["nom_entreprise"]
entreprise.adresse = entreprise_data["adresse"]
entreprise.ville = entreprise_data["ville"]
entreprise.codepostal = entreprise_data["code_postal"]
entreprise.pays = (
entreprise_data["pays"] if entreprise_data["pays"] else "FRANCE"
)
else:
flash(
f'Erreur lors de l\'importation (Feuille "Entreprises", ligne {ligne})'
)
return False
if len(entreprises_import) > 0: # civilite entre H ou F
log = EntrepriseHistorique( if correspondant_data[0].strip() not in ["H", "F"]:
authenticated_user=current_user.user_name, return False
text=f"Importation de {len(entreprises_import)} entreprise(s)",
)
db.session.add(log)
return entreprises_import # entreprise_id existant
entreprise = Entreprise.query.filter_by(siret=correspondant_data[9].strip()).first()
if entreprise is None:
return False
# correspondant possède le meme nom et prénom dans la meme entreprise
correspondant = EntrepriseCorrespondant.query.filter_by(
nom=correspondant_data[1].strip(),
prenom=correspondant_data[2].strip(),
entreprise_id=entreprise.id,
).first()
if correspondant is not None:
return False
if (
correspondant_data[3].strip() == "" and correspondant_data[4].strip() == ""
): # 1 moyen de contact
return False
return True
def check_entreprise_import(entreprise_data): def verif_entreprise_data(entreprise_data):
""" """
Verifie les données d'une ligne Excel (entreprise) Verifie les données d'une ligne Excel (entreprise)
""" """
champs_obligatoires = ["siret", "nom_entreprise", "adresse", "ville", "code_postal"]
for key, value in entreprise_data.items(): # champs obligatoires
if key in champs_obligatoires and value == "":
return False
siret = entreprise_data["siret"]
if EntreprisePreferences.get_check_siret(): if EntreprisePreferences.get_check_siret():
for data in entreprise_data: # champs obligatoires
if data.strip() == "":
return False
else:
for data in entreprise_data[1:]: # champs obligatoires
if data.strip() == "":
return False
if EntreprisePreferences.get_check_siret():
siret = entreprise_data[0].strip().replace(" ", "") # vérification sur le siret
if re.match("^\d{14}$", siret) is None: if re.match("^\d{14}$", siret) is None:
return False return False
try: try:
@ -355,210 +201,7 @@ def check_entreprise_import(entreprise_data):
return False return False
except requests.ConnectionError: except requests.ConnectionError:
return False return False
return True entreprise = Entreprise.query.filter_by(siret=siret).first()
if entreprise is not None:
def check_sites_import(m):
"""
Verifie la feuille Excel "Sites" de l'importation données
"""
sites_import = []
correspondants_import = []
ligne = 1
if m[0] != sum(SITES_KEYS, []):
flash(
f'Veuillez utilisez la feuille excel à remplir (Feuille "Sites", ligne {ligne})'
)
return False, False
l = list_to_dict(m)
for site_data in l:
ligne += 1
site_data["siret_entreprise"] = site_data["siret_entreprise"].replace(" ", "")
if check_site_import(site_data):
entreprise = Entreprise.query.filter_by(
siret=site_data["siret_entreprise"], visible=True
).first()
if site_data["id_site"] == "":
site_import = EntrepriseSite(
entreprise_id=entreprise.id,
nom=site_data["nom_site"],
adresse=site_data["adresse"],
codepostal=site_data["code_postal"],
ville=site_data["ville"],
pays=site_data["pays"],
)
if site_data["civilite"] == "":
sites_import.append(site_import)
else:
correspondant_import = EntrepriseCorrespondant(
entreprise_id=entreprise.id,
civilite=site_data["civilite"],
nom=site_data["nom"],
prenom=site_data["prenom"],
telephone=site_data["telephone"],
mail=site_data["mail"],
poste=site_data["poste"],
service=site_data["service"],
origine=site_data["origine"],
notes=site_data["notes"],
)
sites_import.append(site_import)
correspondants_import.append([site_import, correspondant_import])
else:
site = EntrepriseSite.query.filter_by(id=site_data["id_site"]).first()
site.nom = site_data["nom_site"]
site.adresse = site_data["adresse"]
site.codepostal = site_data["code_postal"]
site.ville = site_data["ville"]
site.pays = site_data["pays"]
if site_data["civilite"] != "":
correspondant_import = EntrepriseCorrespondant(
entreprise_id=entreprise.id,
site_id=site.id,
civilite=site_data["civilite"],
nom=site_data["nom"],
prenom=site_data["prenom"],
telephone=site_data["telephone"],
mail=site_data["mail"],
poste=site_data["poste"],
service=site_data["service"],
origine=site_data["origine"],
notes=site_data["notes"],
)
correspondants_import.append([None, correspondant_import])
else:
flash(f'Erreur lors de l\'importation (Feuille "Sites", ligne {ligne})')
return False, False
if len(sites_import) > 0:
log = EntrepriseHistorique(
authenticated_user=current_user.user_name,
text=f"Importation de {len(sites_import)} site(s)",
)
db.session.add(log)
if len(correspondants_import) > 0:
log = EntrepriseHistorique(
authenticated_user=current_user.user_name,
text=f"Importation de {len(correspondants_import)} correspondant(s)",
)
db.session.add(log)
return sites_import, correspondants_import
def check_site_import(site_data):
"""
Verifie les données d'une ligne Excel (sites)
"""
champs_obligatoires = [
"siret_entreprise",
"nom_site",
"adresse",
"ville",
"code_postal",
"pays",
]
for key, value in site_data.items(): # champs obligatoires
if key in champs_obligatoires and value == "":
return False
if site_data["civilite"] != "":
if check_correspondant_import(site_data) is False:
return False
entreprise = Entreprise.query.filter_by(
siret=site_data["siret_entreprise"], visible=True
).first()
if entreprise is None:
return False
site = EntrepriseSite.query.filter_by(nom=site_data["nom_site"]).first()
if site_data["id_site"] == "" and site is not None:
return False
return True
def check_correspondants_import(m):
ligne = 1
if m[0] != CORRESPONDANTS_KEYS:
flash(
f'Veuillez utilisez la feuille excel à remplir (Feuille "Correspondants", ligne {ligne})'
)
return False
l = list_to_dict(m)
for correspondant_data in l:
ligne += 1
if correspondant_data["id"] == "":
flash(
f'Erreur lors de l\'importation (Feuille "Correspondants", ligne {ligne})'
)
return False
correspondant = EntrepriseCorrespondant.query.filter_by(
id=correspondant_data["id"]
).first()
if correspondant is not None and check_correspondant_import(correspondant_data):
correspondant.civilite = correspondant_data["civilite"]
correspondant.nom = correspondant_data["nom"]
correspondant.prenom = correspondant_data["prenom"]
correspondant.telephone = correspondant_data["telephone"]
correspondant.mail = correspondant_data["mail"]
correspondant.poste = correspondant_data["poste"]
correspondant.service = correspondant_data["service"]
correspondant.origine = correspondant_data["origine"]
correspondant.notes = correspondant_data["notes"]
else:
flash(
f'Erreur lors de l\'importation (Feuille "Correspondants", ligne {ligne})'
)
return False return False
return True return True
def check_correspondant_import(correspondant_data):
"""
Verifie les données d'une ligne Excel (correspondant)
"""
champs_obligatoires = ["civilite", "nom", "prenom"]
for key, value in correspondant_data.items(): # champs obligatoires
if key in champs_obligatoires and value == "":
return False
# civilite entre H ou F
if correspondant_data["civilite"] not in ["H", "F"]:
return False
if (
correspondant_data["telephone"] == "" and correspondant_data["mail"] == ""
): # 1 moyen de contact
return False
if "siret_entreprise" in correspondant_data:
# entreprise_id existant
entreprise = Entreprise.query.filter_by(
siret=correspondant_data["siret_entreprise"], visible=True
).first()
if entreprise is None:
return False
# correspondant possède le meme nom et prénom dans la meme entreprise
correspondant = EntrepriseCorrespondant.query.filter_by(
nom=correspondant_data["nom"],
prenom=correspondant_data["prenom"],
entreprise_id=entreprise.id,
).first()
if correspondant is not None:
return False
return True
def list_to_dict(m):
l = []
for data in m[1:]:
new_dict = {title: value.strip() for title, value in zip(m[0], data)}
l.append(new_dict)
return l

View File

@ -26,7 +26,6 @@
import re import re
import requests import requests
from datetime import datetime
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed, FileRequired from flask_wtf.file import FileField, FileAllowed, FileRequired
@ -34,7 +33,6 @@ from markupsafe import Markup
from sqlalchemy import text from sqlalchemy import text
from wtforms import ( from wtforms import (
StringField, StringField,
IntegerField,
SubmitField, SubmitField,
TextAreaField, TextAreaField,
SelectField, SelectField,
@ -44,23 +42,14 @@ from wtforms import (
BooleanField, BooleanField,
FieldList, FieldList,
FormField, FormField,
BooleanField,
)
from wtforms.validators import (
ValidationError,
DataRequired,
Email,
Optional,
NumberRange,
) )
from wtforms.validators import ValidationError, DataRequired, Email, Optional
from wtforms.widgets import ListWidget, CheckboxInput from wtforms.widgets import ListWidget, CheckboxInput
from app.entreprises.models import ( from app.entreprises.models import (
Entreprise, Entreprise,
EntrepriseCorrespondant, EntrepriseCorrespondant,
EntreprisePreferences, EntreprisePreferences,
EntrepriseSite,
EntrepriseTaxeApprentissage,
) )
from app.models import Identite, Departement from app.models import Identite, Departement
from app.auth.models import User from app.auth.models import User
@ -80,17 +69,11 @@ def _build_string_field(label, required=True, render_kw=None):
return StringField(label, validators=[Optional()], render_kw=render_kw) return StringField(label, validators=[Optional()], render_kw=render_kw)
class EntreprisesFilterForm(FlaskForm):
active = BooleanField("Toutes les entreprises")
association = BooleanField("Seulement les associations partenaires")
class EntrepriseCreationForm(FlaskForm): class EntrepriseCreationForm(FlaskForm):
siret = _build_string_field( siret = _build_string_field(
"SIRET (*)", "SIRET (*)",
render_kw={"placeholder": "Numéro composé de 14 chiffres"}, render_kw={"placeholder": "Numéro composé de 14 chiffres"},
) )
association = BooleanField("Association")
nom_entreprise = _build_string_field("Nom de l'entreprise (*)") nom_entreprise = _build_string_field("Nom de l'entreprise (*)")
adresse = _build_string_field("Adresse de l'entreprise (*)") adresse = _build_string_field("Adresse de l'entreprise (*)")
codepostal = _build_string_field("Code postal de l'entreprise (*)") codepostal = _build_string_field("Code postal de l'entreprise (*)")
@ -170,8 +153,8 @@ class EntrepriseCreationForm(FlaskForm):
class EntrepriseModificationForm(FlaskForm): class EntrepriseModificationForm(FlaskForm):
hidden_entreprise_siret = HiddenField()
siret = StringField("SIRET (*)") siret = StringField("SIRET (*)")
association = BooleanField("Association")
nom = _build_string_field("Nom de l'entreprise (*)") nom = _build_string_field("Nom de l'entreprise (*)")
adresse = _build_string_field("Adresse (*)") adresse = _build_string_field("Adresse (*)")
codepostal = _build_string_field("Code postal (*)") codepostal = _build_string_field("Code postal (*)")
@ -181,11 +164,13 @@ class EntrepriseModificationForm(FlaskForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.siret.render_kw = {"disabled": ""} self.siret.render_kw = {
"disabled": "",
"value": self.hidden_entreprise_siret.data,
}
class SiteCreationForm(FlaskForm): class SiteCreationForm(FlaskForm):
hidden_entreprise_id = HiddenField()
nom = _build_string_field("Nom du site (*)") nom = _build_string_field("Nom du site (*)")
adresse = _build_string_field("Adresse (*)") adresse = _build_string_field("Adresse (*)")
codepostal = _build_string_field("Code postal (*)") codepostal = _build_string_field("Code postal (*)")
@ -193,49 +178,6 @@ class SiteCreationForm(FlaskForm):
pays = _build_string_field("Pays", required=False) pays = _build_string_field("Pays", required=False)
submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE) submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE)
def validate(self):
validate = True
if not FlaskForm.validate(self):
validate = False
site = EntrepriseSite.query.filter_by(
entreprise_id=self.hidden_entreprise_id.data, nom=self.nom.data
).first()
if site is not None:
self.nom.errors.append("Ce site existe déjà (même nom)")
validate = False
return validate
class SiteModificationForm(FlaskForm):
hidden_entreprise_id = HiddenField()
hidden_site_id = HiddenField()
nom = _build_string_field("Nom du site (*)")
adresse = _build_string_field("Adresse (*)")
codepostal = _build_string_field("Code postal (*)")
ville = _build_string_field("Ville (*)")
pays = _build_string_field("Pays", required=False)
submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE)
def validate(self):
validate = True
if not FlaskForm.validate(self):
validate = False
site = EntrepriseSite.query.filter(
EntrepriseSite.entreprise_id == self.hidden_entreprise_id.data,
EntrepriseSite.id != self.hidden_site_id.data,
EntrepriseSite.nom == self.nom.data,
).first()
if site is not None:
self.nom.errors.append("Ce site existe déjà (même nom)")
validate = False
return validate
class MultiCheckboxField(SelectMultipleField): class MultiCheckboxField(SelectMultipleField):
widget = ListWidget(prefix_label=False) widget = ListWidget(prefix_label=False)
@ -272,7 +214,7 @@ class OffreCreationForm(FlaskForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.correspondant.choices = [("", "")] + [ self.correspondant.choices = [
(correspondant.id, f"{correspondant.nom} {correspondant.prenom}") (correspondant.id, f"{correspondant.nom} {correspondant.prenom}")
for correspondant in EntrepriseCorrespondant.query.filter_by( for correspondant in EntrepriseCorrespondant.query.filter_by(
entreprise_id=self.hidden_entreprise_id.data entreprise_id=self.hidden_entreprise_id.data
@ -318,7 +260,7 @@ class OffreModificationForm(FlaskForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.correspondant.choices = [("", "")] + [ self.correspondant.choices = [
(correspondant.id, f"{correspondant.nom} {correspondant.prenom}") (correspondant.id, f"{correspondant.nom} {correspondant.prenom}")
for correspondant in EntrepriseCorrespondant.query.filter_by( for correspondant in EntrepriseCorrespondant.query.filter_by(
entreprise_id=self.hidden_entreprise_id.data entreprise_id=self.hidden_entreprise_id.data
@ -348,16 +290,8 @@ class CorrespondantCreationForm(FlaskForm):
validators=[DataRequired(message=CHAMP_REQUIS)], validators=[DataRequired(message=CHAMP_REQUIS)],
render_kw={"class": "form-control"}, render_kw={"class": "form-control"},
) )
nom = StringField( nom = _build_string_field("Nom (*)", render_kw={"class": "form-control"})
"Nom (*)", prenom = _build_string_field("Prénom (*)", render_kw={"class": "form-control"})
validators=[DataRequired('Le champ "Nom" est requis')],
render_kw={"class": "form-control"},
)
prenom = StringField(
"Prénom (*)",
validators=[DataRequired('Le champ "Prénom" est requis')],
render_kw={"class": "form-control"},
)
telephone = _build_string_field( telephone = _build_string_field(
"Téléphone (*)", required=False, render_kw={"class": "form-control"} "Téléphone (*)", required=False, render_kw={"class": "form-control"}
) )
@ -387,6 +321,7 @@ class CorrespondantCreationForm(FlaskForm):
if not self.telephone.data and not self.mail.data: if not self.telephone.data and not self.mail.data:
msg = "Saisir un moyen de contact (mail ou téléphone)" msg = "Saisir un moyen de contact (mail ou téléphone)"
self.telephone.errors.append(msg) self.telephone.errors.append(msg)
self.mail.errors.append(msg)
validate = False validate = False
return validate return validate
@ -623,75 +558,9 @@ class StageApprentissageModificationForm(FlaskForm):
raise ValidationError("Champ incorrect (selectionnez dans la liste)") raise ValidationError("Champ incorrect (selectionnez dans la liste)")
class TaxeApprentissageForm(FlaskForm):
hidden_entreprise_id = HiddenField()
annee = IntegerField(
"Année (*)",
validators=[
DataRequired(message=CHAMP_REQUIS),
NumberRange(
min=1900,
max=int(datetime.now().strftime("%Y")),
message=f"L'année doit être inférieure ou égale à {int(datetime.now().strftime('%Y'))}",
),
],
default=int(datetime.now().strftime("%Y")),
)
montant = IntegerField(
"Montant (*)",
validators=[
DataRequired(message=CHAMP_REQUIS),
NumberRange(
min=1,
message="Le montant doit être supérieur à 0",
),
],
default=1,
)
notes = TextAreaField("Notes")
submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE)
def validate(self):
validate = True
if not FlaskForm.validate(self):
validate = False
taxe = EntrepriseTaxeApprentissage.query.filter_by(
entreprise_id=self.hidden_entreprise_id.data, annee=self.annee.data
).first()
if taxe is not None:
self.annee.errors.append(
"Une taxe d'apprentissage a déjà été versé pour cette année"
)
validate = False
return validate
class TaxeApprentissageModificationForm(FlaskForm):
annee = IntegerField("Année (*)")
montant = IntegerField(
"Montant (*)",
validators=[
DataRequired(message=CHAMP_REQUIS),
NumberRange(
min=1,
message="Le montant doit être supérieur à 0",
),
],
default=1,
)
notes = TextAreaField("Notes")
submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.annee.render_kw = {"disabled": ""}
class EnvoiOffreForm(FlaskForm): class EnvoiOffreForm(FlaskForm):
responsables = FieldList( responsables = FieldList(
StringField( _build_string_field(
"Responsable (*)", "Responsable (*)",
render_kw={ render_kw={
"placeholder": "Tapez le nom du responsable de formation", "placeholder": "Tapez le nom du responsable de formation",
@ -704,8 +573,6 @@ class EnvoiOffreForm(FlaskForm):
def validate(self): def validate(self):
validate = True validate = True
list_select = True
if not FlaskForm.validate(self): if not FlaskForm.validate(self):
validate = False validate = False
@ -721,12 +588,8 @@ class EnvoiOffreForm(FlaskForm):
.first() .first()
) )
if responsable is None: if responsable is None:
validate, list_select = False, False entry.errors.append("Champ incorrect (selectionnez dans la liste)")
validate = False
if list_select is False:
self.responsables.errors.append(
"Champ incorrect (selectionnez dans la liste)"
)
return validate return validate
@ -748,11 +611,7 @@ class SuppressionConfirmationForm(FlaskForm):
class DesactivationConfirmationForm(FlaskForm): class DesactivationConfirmationForm(FlaskForm):
notes_active = TextAreaField("Notes sur la désactivation", validators=[Optional()]) notes_active = TextAreaField("Notes sur la désactivation", validators=[Optional()])
submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE) submit = SubmitField("Désactiver", render_kw=SUBMIT_MARGE)
class ActivationConfirmationForm(FlaskForm):
submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE)
class ValidationConfirmationForm(FlaskForm): class ValidationConfirmationForm(FlaskForm):
@ -774,7 +633,6 @@ class PreferencesForm(FlaskForm):
mail_entreprise = StringField( mail_entreprise = StringField(
"Mail notifications", "Mail notifications",
validators=[Optional(), Email(message="Adresse e-mail invalide")], validators=[Optional(), Email(message="Adresse e-mail invalide")],
description="utilisé pour envoi mail notification application relations entreprises",
) )
check_siret = BooleanField("Vérification SIRET") check_siret = BooleanField("Vérification SIRET")
submit = SubmitField("Valider", render_kw=SUBMIT_MARGE) submit = SubmitField("Valider", render_kw=SUBMIT_MARGE)

View File

@ -10,7 +10,6 @@ class Entreprise(db.Model):
codepostal = db.Column(db.Text) codepostal = db.Column(db.Text)
ville = db.Column(db.Text) ville = db.Column(db.Text)
pays = db.Column(db.Text) pays = db.Column(db.Text)
association = db.Column(db.Boolean, default=False)
visible = db.Column(db.Boolean, default=False) visible = db.Column(db.Boolean, default=False)
active = db.Column(db.Boolean, default=True) active = db.Column(db.Boolean, default=True)
notes_active = db.Column(db.Text) notes_active = db.Column(db.Text)
@ -37,10 +36,6 @@ class Entreprise(db.Model):
"code_postal": self.codepostal, "code_postal": self.codepostal,
"ville": self.ville, "ville": self.ville,
"pays": self.pays, "pays": self.pays,
"association": self.association,
"visible": self.visible,
"active": self.active,
"notes_active": self.notes_active,
} }
@ -63,18 +58,6 @@ class EntrepriseSite(db.Model):
cascade="all, delete-orphan", cascade="all, delete-orphan",
) )
def to_dict(self):
entreprise = Entreprise.query.get_or_404(self.entreprise_id)
return {
"siret_entreprise": entreprise.siret,
"id_site": self.id,
"nom_site": self.nom,
"adresse": self.adresse,
"code_postal": self.codepostal,
"ville": self.ville,
"pays": self.pays,
}
class EntrepriseCorrespondant(db.Model): class EntrepriseCorrespondant(db.Model):
__tablename__ = "are_correspondants" __tablename__ = "are_correspondants"
@ -94,9 +77,8 @@ class EntrepriseCorrespondant(db.Model):
notes = db.Column(db.Text) notes = db.Column(db.Text)
def to_dict(self): def to_dict(self):
site = EntrepriseSite.query.get_or_404(self.site_id) entreprise = Entreprise.query.filter_by(id=self.entreprise_id).first()
return { return {
"id": self.id,
"civilite": self.civilite, "civilite": self.civilite,
"nom": self.nom, "nom": self.nom,
"prenom": self.prenom, "prenom": self.prenom,
@ -106,7 +88,7 @@ class EntrepriseCorrespondant(db.Model):
"service": self.service, "service": self.service,
"origine": self.origine, "origine": self.origine,
"notes": self.notes, "notes": self.notes,
"nom_site": site.nom, "entreprise_siret": entreprise.siret,
} }
@ -149,14 +131,12 @@ class EntrepriseOffre(db.Model):
} }
class EntrepriseHistorique(db.Model): class EntrepriseLog(db.Model):
__tablename__ = "are_historique" __tablename__ = "are_logs"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now()) date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
authenticated_user = db.Column(db.Text) authenticated_user = db.Column(db.Text)
entreprise_id = db.Column(db.Integer) object = db.Column(db.Integer)
object = db.Column(db.Text)
object_id = db.Column(db.Integer)
text = db.Column(db.Text) text = db.Column(db.Text)
@ -175,17 +155,6 @@ class EntrepriseStageApprentissage(db.Model):
notes = db.Column(db.Text) notes = db.Column(db.Text)
class EntrepriseTaxeApprentissage(db.Model):
__tablename__ = "are_taxe_apprentissage"
id = db.Column(db.Integer, primary_key=True)
entreprise_id = db.Column(
db.Integer, db.ForeignKey("are_entreprises.id", ondelete="cascade")
)
annee = db.Column(db.Integer)
montant = db.Column(db.Integer)
notes = db.Column(db.Text)
class EntrepriseEnvoiOffre(db.Model): class EntrepriseEnvoiOffre(db.Model):
__tablename__ = "are_envoi_offre" __tablename__ = "are_envoi_offre"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)

View File

@ -12,14 +12,11 @@ from app.decorators import permission_required
from app.entreprises import LOGS_LEN from app.entreprises import LOGS_LEN
from app.entreprises.forms import ( from app.entreprises.forms import (
ActivationConfirmationForm,
CorrespondantsCreationForm, CorrespondantsCreationForm,
DesactivationConfirmationForm, DesactivationConfirmationForm,
EntrepriseCreationForm, EntrepriseCreationForm,
EntrepriseModificationForm, EntrepriseModificationForm,
EntreprisesFilterForm,
SiteCreationForm, SiteCreationForm,
SiteModificationForm,
SuppressionConfirmationForm, SuppressionConfirmationForm,
OffreCreationForm, OffreCreationForm,
OffreModificationForm, OffreModificationForm,
@ -30,8 +27,6 @@ from app.entreprises.forms import (
StageApprentissageModificationForm, StageApprentissageModificationForm,
EnvoiOffreForm, EnvoiOffreForm,
AjoutFichierForm, AjoutFichierForm,
TaxeApprentissageForm,
TaxeApprentissageModificationForm,
ValidationConfirmationForm, ValidationConfirmationForm,
ImportForm, ImportForm,
PreferencesForm, PreferencesForm,
@ -41,14 +36,13 @@ from app.entreprises.models import (
Entreprise, Entreprise,
EntrepriseOffre, EntrepriseOffre,
EntrepriseCorrespondant, EntrepriseCorrespondant,
EntrepriseHistorique, EntrepriseLog,
EntrepriseContact, EntrepriseContact,
EntrepriseSite, EntrepriseSite,
EntrepriseStageApprentissage, EntrepriseStageApprentissage,
EntrepriseEnvoiOffre, EntrepriseEnvoiOffre,
EntrepriseOffreDepartement, EntrepriseOffreDepartement,
EntreprisePreferences, EntreprisePreferences,
EntrepriseTaxeApprentissage,
) )
from app.entreprises import app_relations_entreprises as are from app.entreprises import app_relations_entreprises as are
from app.models import Identite from app.models import Identite
@ -58,40 +52,18 @@ from app.scodoc import sco_etud, sco_excel
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import db from app import db
from sqlalchemy import text, sql from sqlalchemy import text
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
@bp.route("/", methods=["GET", "POST"]) @bp.route("/", methods=["GET"])
@permission_required(Permission.RelationsEntreprisesView) @permission_required(Permission.RelationsEntreprisesView)
def index(): def index():
""" """
Permet d'afficher une page avec la liste des entreprises (visible) et une liste des dernières opérations 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, active=True) entreprises = Entreprise.query.filter_by(visible=True, active=True)
logs = ( logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all()
EntrepriseHistorique.query.order_by(EntrepriseHistorique.date.desc())
.limit(LOGS_LEN)
.all()
)
if current_user.has_permission(Permission.RelationsEntreprisesChange, None):
form = EntreprisesFilterForm()
checked = [False, False]
if request.method == "POST":
checked[0] = form.active.data
checked[1] = form.association.data
if checked[0]:
entreprises = Entreprise.query.filter_by(visible=True)
if checked[1]:
entreprises = Entreprise.query.filter_by(association=True)
return render_template(
"entreprises/entreprises.html",
title="Entreprises",
entreprises=entreprises,
logs=logs,
form=form,
checked=checked,
)
return render_template( return render_template(
"entreprises/entreprises.html", "entreprises/entreprises.html",
title="Entreprises", title="Entreprises",
@ -107,9 +79,9 @@ def logs():
Permet d'afficher les logs (toutes les entreprises) Permet d'afficher les logs (toutes les entreprises)
""" """
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
logs = EntrepriseHistorique.query.order_by( logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).paginate(
EntrepriseHistorique.date.desc() page=page, per_page=20
).paginate(page=page, per_page=20) )
return render_template( return render_template(
"entreprises/logs.html", "entreprises/logs.html",
title="Logs", title="Logs",
@ -138,17 +110,11 @@ def correspondants():
Permet d'afficher une page avec la liste des correspondants des entreprises visibles et une liste des dernières opérations Permet d'afficher une page avec la liste des correspondants des entreprises visibles et une liste des dernières opérations
""" """
correspondants = ( correspondants = (
db.session.query(EntrepriseCorrespondant, EntrepriseSite) db.session.query(EntrepriseCorrespondant, Entreprise)
.join(EntrepriseSite, EntrepriseCorrespondant.site_id == EntrepriseSite.id) .join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
.join(Entreprise, EntrepriseSite.entreprise_id == Entreprise.id)
.filter_by(visible=True, active=True) .filter_by(visible=True, active=True)
.all()
)
logs = (
EntrepriseHistorique.query.order_by(EntrepriseHistorique.date.desc())
.limit(LOGS_LEN)
.all()
) )
logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all()
return render_template( return render_template(
"entreprises/correspondants.html", "entreprises/correspondants.html",
title="Correspondants", title="Correspondants",
@ -166,9 +132,9 @@ def fiche_entreprise(id):
La fiche entreprise comporte les informations de l'entreprise, les correspondants de l'entreprise et La fiche entreprise comporte les informations de l'entreprise, les correspondants de l'entreprise et
les offres de l'entreprise. les offres de l'entreprise.
""" """
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( entreprise = Entreprise.query.filter_by(
description=f"fiche entreprise {id} inconnue" id=id, visible=True, active=True
) ).first_or_404(description=f"fiche entreprise {id} inconnue")
offres_with_files = [] offres_with_files = []
depts = are.get_depts() depts = are.get_depts()
for offre in entreprise.offres: for offre in entreprise.offres:
@ -184,8 +150,8 @@ def fiche_entreprise(id):
offres_with_files.append(offre_with_files) offres_with_files.append(offre_with_files)
sites = entreprise.sites[:] sites = entreprise.sites[:]
logs = ( logs = (
EntrepriseHistorique.query.order_by(EntrepriseHistorique.date.desc()) EntrepriseLog.query.order_by(EntrepriseLog.date.desc())
.filter(EntrepriseHistorique.entreprise_id == id) .filter_by(object=id)
.limit(LOGS_LEN) .limit(LOGS_LEN)
.all() .all()
) )
@ -196,11 +162,6 @@ def fiche_entreprise(id):
.join(Identite, Identite.id == EntrepriseStageApprentissage.etudid) .join(Identite, Identite.id == EntrepriseStageApprentissage.etudid)
.all() .all()
) )
taxes = (
EntrepriseTaxeApprentissage.query.filter_by(entreprise_id=id)
.order_by(EntrepriseTaxeApprentissage.annee.desc())
.all()
)
return render_template( return render_template(
"entreprises/fiche_entreprise.html", "entreprises/fiche_entreprise.html",
title="Fiche entreprise", title="Fiche entreprise",
@ -209,7 +170,6 @@ def fiche_entreprise(id):
offres=offres_with_files, offres=offres_with_files,
logs=logs, logs=logs,
stages_apprentissages=stages_apprentissages, stages_apprentissages=stages_apprentissages,
taxes=taxes,
) )
@ -224,8 +184,8 @@ def logs_entreprise(id):
description=f"logs fiche entreprise {id} inconnu" description=f"logs fiche entreprise {id} inconnu"
) )
logs = ( logs = (
EntrepriseHistorique.query.order_by(EntrepriseHistorique.date.desc()) EntrepriseLog.query.order_by(EntrepriseLog.date.desc())
.filter(EntrepriseHistorique.entreprise_id == entreprise.id) .filter_by(object=id)
.paginate(page=page, per_page=20) .paginate(page=page, per_page=20)
) )
return render_template( return render_template(
@ -245,12 +205,12 @@ def fiche_entreprise_validation(id):
entreprise = Entreprise.query.filter_by(id=id, visible=False).first_or_404( entreprise = Entreprise.query.filter_by(id=id, visible=False).first_or_404(
description=f"fiche entreprise (validation) {id} inconnue" description=f"fiche entreprise (validation) {id} inconnue"
) )
sites = entreprise.sites[:] correspondants = entreprise.correspondants
return render_template( return render_template(
"entreprises/fiche_entreprise_validation.html", "entreprises/fiche_entreprise_validation.html",
title="Validation fiche entreprise", title="Validation fiche entreprise",
entreprise=entreprise, entreprise=entreprise,
sites=sites, correspondants=correspondants,
) )
@ -330,7 +290,6 @@ def add_entreprise():
entreprise = Entreprise( entreprise = Entreprise(
nom=form.nom_entreprise.data.strip(), nom=form.nom_entreprise.data.strip(),
siret=form.siret.data.strip(), siret=form.siret.data.strip(),
association=form.association.data,
adresse=form.adresse.data.strip(), adresse=form.adresse.data.strip(),
codepostal=form.codepostal.data.strip(), codepostal=form.codepostal.data.strip(),
ville=form.ville.data.strip(), ville=form.ville.data.strip(),
@ -368,10 +327,9 @@ def add_entreprise():
if current_user.has_permission(Permission.RelationsEntreprisesValidate, None): if current_user.has_permission(Permission.RelationsEntreprisesValidate, None):
entreprise.visible = True entreprise.visible = True
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>" nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>"
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
text=f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom})", text=f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom})",
entreprise_id=entreprise.id,
) )
db.session.add(log) db.session.add(log)
db.session.commit() db.session.commit()
@ -402,52 +360,51 @@ def edit_entreprise(id):
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
description=f"entreprise {id} inconnue" description=f"entreprise {id} inconnue"
) )
form = EntrepriseModificationForm(siret=entreprise.siret) form = EntrepriseModificationForm(hidden_entreprise_siret=entreprise.siret)
if form.validate_on_submit(): if form.validate_on_submit():
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{form.nom.data.strip()}</a>" nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{form.nom.data.strip()}</a>"
if entreprise.nom != form.nom.data.strip(): if entreprise.nom != form.nom.data.strip():
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, object=entreprise.id,
text=f"{nom_entreprise} - Modification du nom (ancien nom: {entreprise.nom})", text=f"{nom_entreprise} - Modification du nom (ancien nom: {entreprise.nom})",
) )
entreprise.nom = form.nom.data.strip() entreprise.nom = form.nom.data.strip()
db.session.add(log) db.session.add(log)
if entreprise.adresse != form.adresse.data.strip(): if entreprise.adresse != form.adresse.data.strip():
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, object=entreprise.id,
text=f"{nom_entreprise} - Modification de l'adresse (ancienne adresse: {entreprise.adresse})", text=f"{nom_entreprise} - Modification de l'adresse (ancienne adresse: {entreprise.adresse})",
) )
entreprise.adresse = form.adresse.data.strip() entreprise.adresse = form.adresse.data.strip()
db.session.add(log) db.session.add(log)
if entreprise.codepostal != form.codepostal.data.strip(): if entreprise.codepostal != form.codepostal.data.strip():
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, object=entreprise.id,
text=f"{nom_entreprise} - Modification du code postal (ancien code postal: {entreprise.codepostal})", text=f"{nom_entreprise} - Modification du code postal (ancien code postal: {entreprise.codepostal})",
) )
entreprise.codepostal = form.codepostal.data.strip() entreprise.codepostal = form.codepostal.data.strip()
db.session.add(log) db.session.add(log)
if entreprise.ville != form.ville.data.strip(): if entreprise.ville != form.ville.data.strip():
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, object=entreprise.id,
text=f"{nom_entreprise} - Modification de la ville (ancienne ville: {entreprise.ville})", text=f"{nom_entreprise} - Modification de la ville (ancienne ville: {entreprise.ville})",
) )
entreprise.ville = form.ville.data.strip() entreprise.ville = form.ville.data.strip()
db.session.add(log) db.session.add(log)
if entreprise.pays != form.pays.data.strip() or not form.pays.data.strip(): if entreprise.pays != form.pays.data.strip() or not form.pays.data.strip():
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, object=entreprise.id,
text=f"{nom_entreprise} - Modification du pays (ancien pays: {entreprise.pays})", text=f"{nom_entreprise} - Modification du pays (ancien pays: {entreprise.pays})",
) )
entreprise.pays = ( entreprise.pays = (
form.pays.data.strip() if form.pays.data.strip() else "FRANCE" form.pays.data.strip() if form.pays.data.strip() else "FRANCE"
) )
db.session.add(log) db.session.add(log)
entreprise.association = form.association.data
db.session.commit() db.session.commit()
flash("L'entreprise a été modifié.") flash("L'entreprise a été modifié.")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
@ -458,7 +415,6 @@ def edit_entreprise(id):
form.codepostal.data = entreprise.codepostal form.codepostal.data = entreprise.codepostal
form.ville.data = entreprise.ville form.ville.data = entreprise.ville
form.pays.data = entreprise.pays form.pays.data = entreprise.pays
form.association.data = entreprise.association
return render_template( return render_template(
"entreprises/form_modification_entreprise.html", "entreprises/form_modification_entreprise.html",
title="Modification entreprise", title="Modification entreprise",
@ -472,128 +428,21 @@ def fiche_entreprise_desactiver(id):
""" """
Permet de désactiver une entreprise Permet de désactiver une entreprise
""" """
entreprise = Entreprise.query.filter_by( entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
id=id, visible=True, active=True description=f"entreprise {id} inconnue"
).first_or_404(description=f"entreprise {id} inconnue") )
form = DesactivationConfirmationForm() form = DesactivationConfirmationForm()
if form.validate_on_submit(): if form.validate_on_submit():
entreprise.notes_active = form.notes_active.data.strip() entreprise.notes_active = form.notes_active.data.strip()
entreprise.active = False entreprise.active = False
db.session.commit() db.session.commit()
flash("L'entreprise a été désactivé.") flash("L'entreprise a été désactivé.")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return redirect(url_for("entreprises.index"))
return render_template( return render_template(
"entreprises/confirmation_form.html", "entreprises/confirmation_form.html",
title="Désactiver entreprise", title="Désactiver entreprise",
form=form, form=form,
info_message="Cliquez sur le bouton Modifier pour confirmer la désactivation", info_message="Cliquez sur le bouton Désactiver pour confirmer la désactivation",
)
@bp.route("/fiche_entreprise/activer/<int:id>", methods=["GET", "POST"])
@permission_required(Permission.RelationsEntreprisesChange)
def fiche_entreprise_activer(id):
"""
Permet d'activer une entreprise
"""
entreprise = Entreprise.query.filter_by(
id=id, visible=True, active=False
).first_or_404(description=f"entreprise {id} inconnue")
form = ActivationConfirmationForm()
if form.validate_on_submit():
entreprise.active = True
db.session.commit()
flash("L'entreprise a été activé.")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
return render_template(
"entreprises/confirmation_form.html",
title="Activer entreprise",
form=form,
info_message="Cliquez sur le bouton Modifier pour confirmer l'activaction",
)
@bp.route("/fiche_entreprise/<int:id>/add_taxe_apprentissage", methods=["GET", "POST"])
def add_taxe_apprentissage(id):
"""
Permet d'ajouter une taxe d'apprentissage sur un fiche entreprise
"""
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
description=f"entreprise {id} inconnue"
)
form = TaxeApprentissageForm(hidden_entreprise_id=id)
if form.validate_on_submit():
taxe = EntrepriseTaxeApprentissage(
entreprise_id=entreprise.id,
annee=form.annee.data,
montant=form.montant.data,
notes=form.notes.data.strip(),
)
db.session.add(taxe)
db.session.commit()
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
return render_template(
"entreprises/form.html",
title="Ajout taxe apprentissage",
form=form,
)
@bp.route(
"/fiche_entreprise/<int:id_entreprise>/edit_taxe_apprentissage/<int:id_taxe>",
methods=["GET", "POST"],
)
def edit_taxe_apprentissage(id_entreprise, id_taxe):
"""
Permet de modifier une taxe d'apprentissage sur un fiche entreprise
"""
entreprise = Entreprise.query.filter_by(
id=id_entreprise, visible=True
).first_or_404(description=f"entreprise {id_entreprise} inconnue")
taxe = EntrepriseTaxeApprentissage.query.filter_by(id=id_taxe).first_or_404(
description=f"taxe d'apprentissage {id_taxe} inconnue"
)
form = TaxeApprentissageModificationForm(annee=taxe.annee)
if form.validate_on_submit():
taxe.montant = form.montant.data
taxe.notes = form.notes.data.strip()
db.session.commit()
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
elif request.method == "GET":
form.montant.data = taxe.montant
form.notes.data = taxe.notes
return render_template(
"entreprises/form.html",
title="Modification taxe apprentissage",
form=form,
)
@bp.route(
"/fiche_entreprise/<int:id_entreprise>/delete_taxe_apprentissage/<int:id_taxe>",
methods=["GET", "POST"],
)
def delete_taxe_apprentissage(id_entreprise, id_taxe):
"""
Permet de modifier une taxe d'apprentissage sur un fiche entreprise
"""
entreprise = Entreprise.query.filter_by(
id=id_entreprise, visible=True
).first_or_404(description=f"entreprise {id_entreprise} inconnue")
taxe = EntrepriseTaxeApprentissage.query.filter_by(id=id_taxe).first_or_404(
description=f"taxe d'apprentissage {id_taxe} inconnue"
)
form = SuppressionConfirmationForm()
if form.validate_on_submit():
db.session.delete(taxe)
db.session.commit()
flash("La taxe d'apprentissage a été supprimé de la liste.")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
return render_template(
"entreprises/confirmation_form.html",
title="Supprimer taxe apprentissage",
form=form,
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
) )
@ -612,10 +461,9 @@ def validate_entreprise(id):
if form.validate_on_submit(): if form.validate_on_submit():
entreprise.visible = True entreprise.visible = True
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>" nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>"
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom}) avec un correspondant",
text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom})",
) )
db.session.add(log) db.session.add(log)
db.session.commit() db.session.commit()
@ -673,9 +521,7 @@ def add_offre(id):
missions=form.missions.data.strip(), missions=form.missions.data.strip(),
duree=form.duree.data.strip(), duree=form.duree.data.strip(),
expiration_date=form.expiration_date.data, expiration_date=form.expiration_date.data,
correspondant_id=form.correspondant.data correspondant_id=form.correspondant.data,
if form.correspondant.data != ""
else None,
) )
db.session.add(offre) db.session.add(offre)
db.session.commit() db.session.commit()
@ -699,11 +545,9 @@ def add_offre(id):
file = form.fichier.data file = form.fichier.data
filename = secure_filename(file.filename) filename = secure_filename(file.filename)
file.save(os.path.join(path, filename)) file.save(os.path.join(path, filename))
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=entreprise.id, object=entreprise.id,
object="offre",
object_id=offre.id,
text="Création d'une offre", text="Création d'une offre",
) )
db.session.add(log) db.session.add(log)
@ -738,10 +582,7 @@ def edit_offre(id):
offre.missions = form.missions.data.strip() offre.missions = form.missions.data.strip()
offre.duree = form.duree.data.strip() offre.duree = form.duree.data.strip()
offre.expiration_date = form.expiration_date.data offre.expiration_date = form.expiration_date.data
if form.correspondant.data == "": offre.correspondant_id = form.correspondant.data
offre.correspondant_id = sql.null()
else:
offre.correspondant_id = form.correspondant.data
if offre_depts_list != form.depts.data: if offre_depts_list != form.depts.data:
for dept in form.depts.data: for dept in form.depts.data:
if dept not in offre_depts_list: if dept not in offre_depts_list:
@ -756,11 +597,9 @@ def edit_offre(id):
offre_id=offre.id, dept_id=dept offre_id=offre.id, dept_id=dept
).first_or_404() ).first_or_404()
db.session.delete(offre_dept) db.session.delete(offre_dept)
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=offre.entreprise_id, object=offre.entreprise_id,
object="offre",
object_id=offre.id,
text="Modification d'une offre", text="Modification d'une offre",
) )
db.session.add(log) db.session.add(log)
@ -803,11 +642,9 @@ def delete_offre(id):
) )
if os.path.isdir(path): if os.path.isdir(path):
shutil.rmtree(path) shutil.rmtree(path)
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=offre.entreprise_id, object=offre.entreprise_id,
object="offre",
object_id=offre.id,
text="Suppression d'une offre", text="Suppression d'une offre",
) )
db.session.add(log) db.session.add(log)
@ -863,7 +700,7 @@ def add_site(id):
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
description=f"entreprise {id} inconnue" description=f"entreprise {id} inconnue"
) )
form = SiteCreationForm(hidden_entreprise_id=id) form = SiteCreationForm()
if form.validate_on_submit(): if form.validate_on_submit():
site = EntrepriseSite( site = EntrepriseSite(
entreprise_id=entreprise.id, entreprise_id=entreprise.id,
@ -884,41 +721,6 @@ def add_site(id):
) )
@bp.route(
"/fiche_entreprise/<int:id_entreprise>/edit_site/<int:id_site>",
methods=["GET", "POST"],
)
def edit_site(id_entreprise, id_site):
entreprise = Entreprise.query.filter_by(
id=id_entreprise, visible=True
).first_or_404(description=f"entreprise {id_entreprise} inconnue")
site = EntrepriseSite.query.filter_by(
id=id_site, entreprise_id=entreprise.id
).first_or_404(description=f"site {id_site} inconnu")
form = SiteModificationForm(
hidden_entreprise_id=id_entreprise, hidden_site_id=id_site
)
if form.validate_on_submit():
site.nom = form.nom.data.strip()
site.adresse = form.adresse.data.strip()
site.codepostal = form.codepostal.data.strip()
site.ville = form.ville.data.strip()
site.pays = (form.pays.data.strip() if form.pays.data.strip() else "FRANCE",)
db.session.commit()
return redirect(url_for("entreprises.fiche_entreprise", id=site.entreprise_id))
elif request.method == "GET":
form.nom.data = site.nom
form.adresse.data = site.adresse
form.codepostal.data = site.codepostal
form.ville.data = site.ville
form.pays.data = site.pays
return render_template(
"entreprises/form.html",
title="Modification site",
form=form,
)
@bp.route( @bp.route(
"/fiche_entreprise/<int:id_entreprise>/add_correspondant/<int:id_site>", "/fiche_entreprise/<int:id_entreprise>/add_correspondant/<int:id_site>",
methods=["GET", "POST"], methods=["GET", "POST"],
@ -950,17 +752,13 @@ def add_correspondant(id_entreprise, id_site):
origine=correspondant_entry.origine.data.strip(), origine=correspondant_entry.origine.data.strip(),
notes=correspondant_entry.notes.data.strip(), notes=correspondant_entry.notes.data.strip(),
) )
db.session.add(correspondant) log = EntrepriseLog(
db.session.commit()
db.session.refresh(correspondant)
log = EntrepriseHistorique(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=correspondant.entreprise_id, object=entreprise.id,
object="correspondant",
object_id=correspondant.id,
text="Création d'un correspondant", text="Création d'un correspondant",
) )
db.session.add(log) db.session.add(log)
db.session.add(correspondant)
db.session.commit() db.session.commit()
flash("Le correspondant a été ajouté à la fiche entreprise.") flash("Le correspondant a été ajouté à la fiche entreprise.")
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
@ -977,11 +775,8 @@ def edit_correspondant(id):
""" """
Permet de modifier un correspondant Permet de modifier un correspondant
""" """
correspondant = ( correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404(
db.session.query(EntrepriseCorrespondant) description=f"correspondant {id} inconnu"
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
.filter(EntrepriseCorrespondant.id == id, Entreprise.visible == True)
.first_or_404(description=f"correspondant {id} inconnu")
) )
form = CorrespondantModificationForm( form = CorrespondantModificationForm(
hidden_entreprise_id=correspondant.entreprise_id, hidden_entreprise_id=correspondant.entreprise_id,
@ -997,11 +792,9 @@ def edit_correspondant(id):
correspondant.service = form.service.data.strip() correspondant.service = form.service.data.strip()
correspondant.origine = form.origine.data.strip() correspondant.origine = form.origine.data.strip()
correspondant.notes = form.notes.data.strip() correspondant.notes = form.notes.data.strip()
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=correspondant.entreprise_id, object=correspondant.entreprise_id,
object="correspondant",
object_id=correspondant.id,
text="Modification d'un correspondant", text="Modification d'un correspondant",
) )
db.session.add(log) db.session.add(log)
@ -1033,20 +826,15 @@ def delete_correspondant(id):
""" """
Permet de supprimer un correspondant Permet de supprimer un correspondant
""" """
correspondant = ( correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404(
db.session.query(EntrepriseCorrespondant) description=f"correspondant {id} inconnu"
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
.filter(EntrepriseCorrespondant.id == id, Entreprise.visible == True)
.first_or_404(description=f"correspondant {id} inconnu")
) )
form = SuppressionConfirmationForm() form = SuppressionConfirmationForm()
if form.validate_on_submit(): if form.validate_on_submit():
db.session.delete(correspondant) db.session.delete(correspondant)
log = EntrepriseHistorique( log = EntrepriseLog(
authenticated_user=current_user.user_name, authenticated_user=current_user.user_name,
entreprise_id=correspondant.entreprise_id, object=correspondant.entreprise_id,
object="correspondant",
object_id=correspondant.id,
text="Suppression d'un correspondant", text="Suppression d'un correspondant",
) )
db.session.add(log) db.session.add(log)
@ -1149,10 +937,7 @@ def contacts(id):
""" """
Permet d'afficher une page avec la liste des contacts d'une entreprise Permet d'afficher une page avec la liste des contacts d'une entreprise
""" """
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( contacts = EntrepriseContact.query.filter_by(entreprise=id).all()
description=f"entreprise {id} inconnue"
)
contacts = EntrepriseContact.query.filter_by(entreprise=entreprise.id).all()
return render_template( return render_template(
"entreprises/contacts.html", "entreprises/contacts.html",
title="Liste des contacts", title="Liste des contacts",
@ -1340,7 +1125,7 @@ def json_etudiants():
if request.args.get("term") is None: if request.args.get("term") is None:
abort(400) abort(400)
term = request.args.get("term").strip() term = request.args.get("term").strip()
etudiants = Identite.query.filter(Identite.nom.ilike(f"%{term}%")).limit(30).all() etudiants = Identite.query.filter(Identite.nom.ilike(f"%{term}%")).all()
list = [] list = []
for etudiant in etudiants: for etudiant in etudiants:
content = {} content = {}
@ -1349,14 +1134,10 @@ def json_etudiants():
content = { content = {
"id": f"{etudiant.id}", "id": f"{etudiant.id}",
"value": value, "value": value,
"info": f"Département {are.get_dept_acronym_by_id(etudiant.dept_id)} - {etudiant.inscription_courante().formsemestre.titre}", "info": f"{etudiant.inscription_courante().formsemestre.titre}",
} }
else: else:
content = { content = {"id": f"{etudiant.id}", "value": value}
"id": f"{etudiant.id}",
"value": value,
"info": f"Département {are.get_dept_acronym_by_id(etudiant.dept_id)}",
}
list.append(content) list.append(content)
return jsonify(results=list) return jsonify(results=list)
@ -1370,56 +1151,68 @@ def json_responsables():
if request.args.get("term") is None: if request.args.get("term") is None:
abort(400) abort(400)
term = request.args.get("term").strip() term = request.args.get("term").strip()
responsables = ( responsables = User.query.filter(
User.query.filter( User.nom.ilike(f"%{term}%"), User.nom.is_not(None), User.prenom.is_not(None)
User.nom.ilike(f"%{term}%"), User.nom.is_not(None), User.prenom.is_not(None) ).all()
)
.limit(30)
.all()
)
list = [] list = []
for responsable in responsables: for responsable in responsables:
content = {} content = {}
value = f"{responsable.get_nomplogin()}" value = f"{responsable.get_nomplogin()}"
content = {"id": f"{responsable.id}", "value": value} content = {"id": f"{responsable.id}", "value": value, "info": ""}
list.append(content) list.append(content)
return jsonify(results=list) return jsonify(results=list)
@bp.route("/export_donnees") @bp.route("/export_entreprises")
@permission_required(Permission.RelationsEntreprisesExport) @permission_required(Permission.RelationsEntreprisesExport)
def export_donnees(): def export_entreprises():
""" """
Permet d'exporter la liste des entreprises sous format excel (.xlsx) Permet d'exporter la liste des entreprises sous format excel (.xlsx)
""" """
entreprise = Entreprise.query.filter_by(visible=True).first() entreprises = Entreprise.query.filter_by(visible=True).all()
if entreprise: if entreprises:
wb = are.get_excel_book_are(export=True) keys = ["siret", "nom_entreprise", "adresse", "ville", "code_postal", "pays"]
xlsx = wb.generate() titles = keys[:]
filename = "ExportApplicationRelationsEntreprises" 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) return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
else: else:
flash("Aucune entreprise dans la base.")
return redirect(url_for("entreprises.index")) return redirect(url_for("entreprises.index"))
@bp.route("/import_donnees/get_file_sample") @bp.route("/import_entreprises/get_import_entreprises_file_sample")
@permission_required(Permission.RelationsEntreprisesExport) @permission_required(Permission.RelationsEntreprisesExport)
def get_import_donnees_file_sample(): def get_import_entreprises_file_sample():
""" """
Permet de récupérer un fichier exemple vide pour pouvoir importer des entreprises Permet de récupérer un fichier exemple vide pour pouvoir importer des entreprises
""" """
wb = are.get_excel_book_are() keys = [
xlsx = wb.generate() "siret",
filename = "ImportApplicationRelationsEntreprises" "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) return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
@bp.route("/import_donnees", methods=["GET", "POST"]) @bp.route("/import_entreprises", methods=["GET", "POST"])
@permission_required(Permission.RelationsEntreprisesExport) @permission_required(Permission.RelationsEntreprisesExport)
def import_donnees(): def import_entreprises():
""" """
Permet d'importer des entreprises à partir d'un fichier excel (.xlsx) Permet d'importer des entreprises a l'aide d'un fichier excel (.xlsx)
""" """
form = ImportForm() form = ImportForm()
if form.validate_on_submit(): if form.validate_on_submit():
@ -1428,58 +1221,237 @@ def import_donnees():
Config.SCODOC_VAR_DIR, "tmp", secure_filename(file.filename) Config.SCODOC_VAR_DIR, "tmp", secure_filename(file.filename)
) )
file.save(file_path) file.save(file_path)
diag, lm = sco_excel.excel_workbook_to_list(file_path) data = sco_excel.excel_file_to_list(file_path)
os.remove(file_path) os.remove(file_path)
if lm is None or len(lm) < 2: 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") flash("Veuillez utilisez la feuille excel à remplir")
return redirect(url_for("entreprises.import_donnees")) return render_template(
entreprises_import = are.check_entreprises_import(lm[0]) "entreprises/import_entreprises.html",
sites_import, correspondants_import = are.check_sites_import(lm[1]) title="Importation entreprises",
if ( form=form,
entreprises_import is False
or sites_import is False
or correspondants_import is False
or (len(lm) > 2 and are.check_correspondants_import(lm[2]) is False)
):
return redirect(url_for("entreprises.import_donnees"))
for entreprise in entreprises_import:
db.session.add(entreprise)
db.session.commit()
db.session.refresh(entreprise)
site = EntrepriseSite(
entreprise_id=entreprise.id,
nom=entreprise.nom,
adresse=entreprise.adresse,
codepostal=entreprise.codepostal,
ville=entreprise.ville,
pays=entreprise.pays,
) )
db.session.add(site) for entreprise_data in data[1][1:]:
for site in sites_import: ligne += 1
db.session.add(site) if (
correspondants = [] are.verif_entreprise_data(entreprise_data)
for site, correspondant in correspondants_import: and entreprise_data[0].replace(" ", "") not in siret_list
if site is None: ):
db.session.add(correspondant) siret_list.append(entreprise_data[0].replace(" ", ""))
entreprise = Entreprise(
siret=entreprise_data[0].replace(" ", ""),
nom=entreprise_data[1].strip(),
adresse=entreprise_data[2].strip(),
ville=entreprise_data[3].strip(),
codepostal=entreprise_data[4].strip(),
pays=entreprise_data[5].strip(),
visible=True,
)
entreprises_import.append(entreprise)
else: else:
db.session.add(site) flash(f"Erreur lors de l'importation (ligne {ligne})")
db.session.commit() return render_template(
db.session.refresh(site) "entreprises/import_entreprises.html",
correspondant.site_id = site.id title="Importation entreprises",
db.session.add(correspondant) form=form,
correspondants.append(correspondant) )
db.session.commit()
flash(f"Importation réussie") if len(entreprises_import) > 0:
return render_template( for entreprise in entreprises_import:
"entreprises/import_donnees.html", db.session.add(entreprise)
title="Importation données", log = EntrepriseLog(
form=form, authenticated_user=current_user.user_name,
entreprises_import=entreprises_import, text=f"Importation de {len(entreprises_import)} entreprise(s)",
sites_import=sites_import, )
correspondants_import=correspondants, 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( return render_template(
"entreprises/import_donnees.html", title="Importation données", form=form "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 = [
"civilite",
"nom",
"prenom",
"telephone",
"mail",
"poste",
"service",
"origine",
"notes",
"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:
flash("Aucun correspondant dans la base.")
return redirect(url_for("entreprises.correspondants"))
@bp.route("/import_correspondants/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 = [
"civilite",
"nom",
"prenom",
"telephone",
"mail",
"poste",
"service",
"origine",
"notes",
"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 = [
"civilite",
"nom",
"prenom",
"telephone",
"mail",
"poste",
"service",
"origine",
"notes",
"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[1].strip(),
correspondant_data[2].strip(),
correspondant_data[9].strip(),
)
not in correspondant_list
):
correspondant_list.append(
(
correspondant_data[1].strip(),
correspondant_data[2].strip(),
correspondant_data[9].strip(),
)
)
entreprise = Entreprise.query.filter_by(
siret=correspondant_data[9].strip()
).first()
correspondant = EntrepriseCorrespondant(
civilite=correspondant_data[0].strip(),
nom=correspondant_data[1].strip(),
prenom=correspondant_data[2].strip(),
telephone=correspondant_data[3].strip(),
mail=correspondant_data[4].strip(),
poste=correspondant_data[5].strip(),
service=correspondant_data[6].strip(),
origine=correspondant_data[7].strip(),
notes=correspondant_data[8].strip(),
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,
) )

View File

@ -132,10 +132,13 @@ class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):
if sco_preferences.get_preference( if sco_preferences.get_preference(
"bul_show_minmax_mod", formsemestre_id "bul_show_minmax_mod", formsemestre_id
): ):
rang_minmax = '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>' % ( rang_minmax = (
mod["mod_rang_txt"], '%s <span class="bul_minmax" title="[min, max] UE">[%s, %s]</span>'
scu.fmt_note(mod["stats"]["min"]), % (
scu.fmt_note(mod["stats"]["max"]), mod["mod_rang_txt"],
scu.fmt_note(mod["stats"]["min"]),
scu.fmt_note(mod["stats"]["max"]),
)
) )
else: else:
rang_minmax = mod["mod_rang_txt"] # vide si pas option rang rang_minmax = mod["mod_rang_txt"] # vide si pas option rang

View File

@ -75,7 +75,7 @@ import sco_version
def assemble_bulletins_pdf( def assemble_bulletins_pdf(
formsemestre_id: int, formsemestre_id: int,
story: list, story,
bul_title: str, bul_title: str,
infos, infos,
pagesbookmarks=None, pagesbookmarks=None,
@ -107,7 +107,7 @@ def assemble_bulletins_pdf(
preferences=sco_preferences.SemPreferences(formsemestre_id), preferences=sco_preferences.SemPreferences(formsemestre_id),
) )
) )
document.multiBuild(story) document.build(story)
data = report.getvalue() data = report.getvalue()
return data return data

View File

@ -40,9 +40,10 @@ from openpyxl.comments import Comment
from openpyxl import Workbook, load_workbook from openpyxl import Workbook, load_workbook
from openpyxl.cell import WriteOnlyCell from openpyxl.cell import WriteOnlyCell
from openpyxl.styles import Font, Border, Side, Alignment, PatternFill from openpyxl.styles import Font, Border, Side, Alignment, PatternFill
from openpyxl.worksheet.worksheet import Worksheet
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app.scodoc import notesdb
from app.scodoc import sco_preferences
from app import log from app import log
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
@ -592,87 +593,60 @@ def excel_feuille_saisie(e, titreannee, description, lines):
def excel_bytes_to_list(bytes_content): def excel_bytes_to_list(bytes_content):
try: try:
filelike = io.BytesIO(bytes_content) filelike = io.BytesIO(bytes_content)
except Exception as exc: return _excel_to_list(filelike)
except:
raise ScoValueError( raise ScoValueError(
"""Le fichier xlsx attendu n'est pas lisible ! """Le fichier xlsx attendu n'est pas lisible !
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ..) Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ..)
""" """
) from exc )
return _excel_to_list(filelike)
def excel_file_to_list(filename): def excel_file_to_list(filename):
try: try:
return _excel_to_list(filename) return _excel_to_list(filename)
except Exception as exc: except:
raise ScoValueError( raise ScoValueError(
"""Le fichier xlsx attendu n'est pas lisible ! """Le fichier xlsx attendu n'est pas lisible !
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...) Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...)
""" """
) from exc )
def excel_workbook_to_list(filename):
try:
return _excel_workbook_to_list(filename)
except Exception as exc:
raise ScoValueError(
"""Le fichier xlsx attendu n'est pas lisible !
Peut-être avez-vous fourni un fichier au mauvais format (txt, xls, ...)
"""
) from exc
def _open_workbook(filelike, dump_debug=False) -> Workbook:
"""Open document.
On error, if dump-debug is True, dump data in /tmp for debugging purpose
"""
try:
workbook = load_workbook(filename=filelike, read_only=True, data_only=True)
except Exception as exc:
log("Excel_to_list: failure to import document")
if dump_debug:
dump_filename = "/tmp/last_scodoc_import_failure" + scu.XLSX_SUFFIX
log(f"Dumping problemetic file on {dump_filename}")
with open(dump_filename, "wb") as f:
f.write(filelike)
raise ScoValueError(
"Fichier illisible: assurez-vous qu'il s'agit bien d'un document Excel xlsx !"
) from exc
return workbook
def _excel_to_list(filelike): def _excel_to_list(filelike):
"""returns list of list""" """returns list of list
workbook = _open_workbook(filelike) convert_to_string is a conversion function applied to all non-string values (ie numbers)
"""
try:
wb = load_workbook(filename=filelike, read_only=True, data_only=True)
except:
log("Excel_to_list: failure to import document")
with open("/tmp/last_scodoc_import_failure" + scu.XLSX_SUFFIX, "wb") as f:
f.write(filelike)
raise ScoValueError(
"Fichier illisible: assurez-vous qu'il s'agit bien d'un document Excel !"
)
diag = [] # liste de chaines pour former message d'erreur diag = [] # liste de chaines pour former message d'erreur
if len(workbook.get_sheet_names()) < 1: # n'utilise que la première feuille
if len(wb.get_sheet_names()) < 1:
diag.append("Aucune feuille trouvée dans le classeur !") diag.append("Aucune feuille trouvée dans le classeur !")
return diag, None return diag, None
# n'utilise que la première feuille: if len(wb.get_sheet_names()) > 1:
if len(workbook.get_sheet_names()) > 1:
diag.append("Attention: n'utilise que la première feuille du classeur !") diag.append("Attention: n'utilise que la première feuille du classeur !")
sheet_name = workbook.get_sheet_names()[0]
ws = workbook[sheet_name]
diag_sheet, matrix = _excel_sheet_to_list(ws, sheet_name)
diag += diag_sheet
return diag, matrix
def _excel_sheet_to_list(sheet: Worksheet, sheet_name: str) -> tuple[list, list]:
"""read a spreadsheet sheet, and returns:
- diag : a list of strings (error messages aimed at helping the user)
- a list of lists: the spreadsheet cells
"""
diag = []
# fill matrix # fill matrix
sheet_name = wb.get_sheet_names()[0]
ws = wb.get_sheet_by_name(sheet_name)
sheet_name = sheet_name.encode(scu.SCO_ENCODING, "backslashreplace")
values = {} values = {}
for row in sheet.iter_rows(): for row in ws.iter_rows():
for cell in row: for cell in row:
if cell.value is not None: if cell.value is not None:
values[(cell.row - 1, cell.column - 1)] = str(cell.value) values[(cell.row - 1, cell.column - 1)] = str(cell.value)
if not values: if not values:
diag.append(f"Aucune valeur trouvée dans la feuille {sheet_name} !") diag.append(
"Aucune valeur trouvée dans la feuille %s !"
% sheet_name.decode(scu.SCO_ENCODING)
)
return diag, None return diag, None
indexes = list(values.keys()) indexes = list(values.keys())
# search numbers of rows and cols # search numbers of rows and cols
@ -680,38 +654,23 @@ def _excel_sheet_to_list(sheet: Worksheet, sheet_name: str) -> tuple[list, list]
cols = [x[1] for x in indexes] cols = [x[1] for x in indexes]
nbcols = max(cols) + 1 nbcols = max(cols) + 1
nbrows = max(rows) + 1 nbrows = max(rows) + 1
matrix = [] m = []
for _ in range(nbrows): for _ in range(nbrows):
matrix.append([""] * nbcols) m.append([""] * nbcols)
for row_idx, col_idx in indexes: for row_idx, col_idx in indexes:
v = values[(row_idx, col_idx)] v = values[(row_idx, col_idx)]
matrix[row_idx][col_idx] = v # if isinstance(v, six.text_type):
diag.append(f'Feuille "{sheet_name}", {len(matrix)} lignes') # v = v.encode(scu.SCO_ENCODING, "backslashreplace")
# elif convert_to_string:
return diag, matrix # v = convert_to_string(v)
m[row_idx][col_idx] = v
diag.append(
def _excel_workbook_to_list(filelike): 'Feuille "%s", %d lignes' % (sheet_name.decode(scu.SCO_ENCODING), len(m))
"""Lit un classeur (workbook): chaque feuille est lue )
et est convertie en une liste de listes. # diag.append(str(M))
Returns: #
- diag : a list of strings (error messages aimed at helping the user) return diag, m
- a list of lists: the spreadsheet cells
"""
workbook = _open_workbook(filelike)
diag = [] # liste de chaines pour former message d'erreur
if len(workbook.get_sheet_names()) < 1:
diag.append("Aucune feuille trouvée dans le classeur !")
return diag, None
matrix_list = []
for sheet_name in workbook.get_sheet_names():
# fill matrix
sheet = workbook.get_sheet_by_name(sheet_name)
diag_sheet, matrix = _excel_sheet_to_list(sheet, sheet_name)
diag += diag_sheet
matrix_list.append(matrix)
return diag, matrix_list
def excel_feuille_listeappel( def excel_feuille_listeappel(

View File

@ -121,7 +121,8 @@ def _list_dept_logos(dept_id=None, prefix=scu.LOGO_FILE_PREFIX):
:return: le résultat de la recherche ou None si aucune image trouvée :return: le résultat de la recherche ou None si aucune image trouvée
""" """
allowed_ext = "|".join(scu.LOGOS_IMAGES_ALLOWED_TYPES) allowed_ext = "|".join(scu.LOGOS_IMAGES_ALLOWED_TYPES)
filename_parser = re.compile(f"{prefix}([^.]*).({allowed_ext})") # parse filename 'logo_<logoname>.<ext> . be carefull: logoname may include '.'
filename_parser = re.compile(f"{prefix}(([^.]*.)+)({allowed_ext})")
logos = {} logos = {}
path_dir = Path(scu.SCODOC_LOGOS_DIR) path_dir = Path(scu.SCODOC_LOGOS_DIR)
if dept_id: if dept_id:
@ -135,7 +136,7 @@ def _list_dept_logos(dept_id=None, prefix=scu.LOGO_FILE_PREFIX):
if os.access(path_dir.joinpath(entry).absolute(), os.R_OK): if os.access(path_dir.joinpath(entry).absolute(), os.R_OK):
result = filename_parser.match(entry.name) result = filename_parser.match(entry.name)
if result: if result:
logoname = result.group(1) logoname = result.group(1)[:-1] # retreive logoname from filename (less final dot)
logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).select() logos[logoname] = Logo(logoname=logoname, dept_id=dept_id).select()
return logos if len(logos.keys()) > 0 else None return logos if len(logos.keys()) > 0 else None
@ -191,6 +192,9 @@ class Logo:
) )
self.mm = "Not initialized: call the select or create function before access" self.mm = "Not initialized: call the select or create function before access"
def __repr__(self) -> str:
return f"Logo(logoname='{self.logoname}', filename='{self.filename}')"
def _set_format(self, fmt): def _set_format(self, fmt):
self.suffix = fmt self.suffix = fmt
self.filepath = self.basepath + "." + fmt self.filepath = self.basepath + "." + fmt

View File

@ -303,9 +303,12 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
) )
for mod in options: for mod in options:
if can_change: if can_change:
c_link = '<a class="discretelink" href="moduleimpl_inscriptions_edit?moduleimpl_id=%s">%s</a>' % ( c_link = (
mod["moduleimpl_id"], '<a class="discretelink" href="moduleimpl_inscriptions_edit?moduleimpl_id=%s">%s</a>'
mod["descri"] or "<i>(inscrire des étudiants)</i>", % (
mod["moduleimpl_id"],
mod["descri"] or "<i>(inscrire des étudiants)</i>",
)
) )
else: else:
c_link = mod["descri"] c_link = mod["descri"]

View File

@ -1,37 +1,28 @@
.nav-entreprise { .nav-entreprise>ul {
text-align: left; padding-left: 0;
}
.nav-entreprise ul {
padding: 0;
} }
.nav-entreprise li{ .nav-entreprise li{
list-style: none; list-style: none;
display: inline-block; display: inline-block;
padding: 10px; padding: 10px;
border: 2px black solid;
border-radius: 10px;
}
.nav-entreprise li:hover{
background-color: rgb(212, 212, 212);
} }
.nav-entreprise>ul>li>a { .nav-entreprise>ul>li>a {
text-decoration: none; text-decoration: none;
color: black; color: black;
padding: 15px; padding: 15px;
}
.nav-entreprise>ul>li>a:hover {
text-decoration: underline;
} }
.form-error { .form-error {
color: #a94442; color: #a94442;
} }
.nav-entreprise>ul>li>a:hover {
color: red;
}
.boutons .btn { .boutons .btn {
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
@ -68,33 +59,14 @@
margin-bottom: -5px; margin-bottom: -5px;
} }
.entreprise, .correspondant, .offre, .site, .info-active { .entreprise, .correspondant, .offre, .site{
border: solid 2px black; border: solid 2px;
border-radius: 10px; border-radius: 10px;
padding: 10px; padding: 10px;
margin-bottom: 10px; margin-bottom: 10px;
margin-top: 10px; margin-top: 10px;
} }
.info-active {
border-color: red;
background-color: rgb(250, 220, 220);
}
.entreprise {
display: flex;
justify-content: space-between;
}
.entreprise > div {
flex: 1 0 0;
}
.taxe-apprentissage{
overflow-y: scroll;
height: 100px;
}
.sites-et-offres { .sites-et-offres {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -129,47 +101,4 @@
border: solid 2px; border: solid 2px;
border-radius: 10px; border-radius: 10px;
padding: 10px; padding: 10px;
}
#liste-taxes-apprentissages {
list-style: none;
padding-left: 0;
}
#form-entreprise-filter > label {
margin-right: 20px;
}
.title-form-error {
font-weight: bold;
color: #a94442;
}
.breadcrumbs {
padding: 0;
}
.breadcrumbs_item {
display: inline-block;
}
.breadcrumbs_item:not(:last-of-type)::after {
content: '\203a';
margin: 0 5px;
color: #777;
}
.breadcrumbs_link {
text-decoration: none;
color: #777;
}
.breadcrumbs_link:hover {
text-decoration: underline;
color: #333;
}
.breadcrumbs_link-active {
color: #333;
font-weight: bold;
} }

View File

@ -16,11 +16,7 @@
</p> </p>
<form method="POST" action="" novalidate> <form method="POST" action="" novalidate>
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
{{ form.correspondants.label }}
{% for subfield in form.correspondants %} {% for subfield in form.correspondants %}
{% if subfield.errors %}
<p class="title-form-error">Formulaire {{ subfield.label.text }}</p>
{% endif %}
{% for subsubfield in subfield %} {% for subsubfield in subfield %}
{% if subsubfield.errors %} {% if subsubfield.errors %}
{% for error in subsubfield.errors %} {% for error in subsubfield.errors %}
@ -60,22 +56,7 @@
} }
let newFieldName = `correspondants-${Math.max(...correspondantInputIds) + 1}`; let newFieldName = `correspondants-${Math.max(...correspondantInputIds) + 1}`;
allCorrepondantsFieldWrapper.insertAdjacentHTML('beforeend',` allCorrepondantsFieldWrapper.insertAdjacentHTML('beforeend',`
<li> <li><label for="${newFieldName}">Correspondants-${Math.max(...correspondantInputIds) + 1}</label><table id="${newFieldName}"><tr><th><label for="${newFieldName}-civilite">Civilité (*)</label></th><td><select class="form-control" id="${newFieldName}-civilite" name="${newFieldName}-civilite" required><option value="H">Monsieur</option><option value="F">Madame</option></select></td></tr><tr><th><label for="${newFieldName}-nom">Nom (*)</label></th><td><input class="form-control" id="${newFieldName}-nom" name="${newFieldName}-nom" required type="text" value=""></td></tr><tr><th><label for="${newFieldName}-prenom">Prénom (*)</label></th><td><input class="form-control" id="${newFieldName}-prenom" name="${newFieldName}-prenom" required type="text" value=""></td></tr><tr><th><label for="${newFieldName}-telephone">Téléphone (*)</label></th><td><input class="form-control" id="${newFieldName}-telephone" name="${newFieldName}-telephone" type="text" value=""></td></tr><tr><th><label for="${newFieldName}-mail">Mail (*)</label></th><td><input class="form-control" id="${newFieldName}-mail" name="${newFieldName}-mail" type="text" value=""></td></tr><tr><th><label for="${newFieldName}-poste">Poste</label></th><td><input class="form-control" id="${newFieldName}-poste" name="${newFieldName}-poste" type="text" value=""></td></tr><tr><th><label for="${newFieldName}-service">Service</label></th><td><input class="form-control" id="${newFieldName}-service" name="${newFieldName}-service" type="text" value=""></td></tr><tr><th><label for="${newFieldName}-origine">Origine</label></th><td><input class="form-control" id="${newFieldName}-origine" name="${newFieldName}-origine" type="text" value=""></td></tr><tr><th><label for="${newFieldName}-notes">Notes</label></th><td><input class="form-control" id="${newFieldName}-notes" name="${newFieldName}-notes" type="text" value=""></td></tr></table><input id="${newFieldName}-csrf_token" name="${newFieldName}-csrf_token" type="hidden" value=${csrf_token}><div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer ce correspondant</div></li>
<label for="${newFieldName}">Correspondants-${Math.max(...correspondantInputIds) + 1}</label>
<table id="${newFieldName}">
<tr><th><label for="${newFieldName}-civilite">Civilité (*)</label></th><td><select class="form-control" id="${newFieldName}-civilite" name="${newFieldName}-civilite" required><option value="H">Monsieur</option><option value="F">Madame</option></select></td></tr>
<tr><th><label for="${newFieldName}-nom">Nom (*)</label></th><td><input class="form-control" id="${newFieldName}-nom" name="${newFieldName}-nom" required type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-prenom">Prénom (*)</label></th><td><input class="form-control" id="${newFieldName}-prenom" name="${newFieldName}-prenom" required type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-telephone">Téléphone (*)</label></th><td><input class="form-control" id="${newFieldName}-telephone" name="${newFieldName}-telephone" type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-mail">Mail (*)</label></th><td><input class="form-control" id="${newFieldName}-mail" name="${newFieldName}-mail" type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-poste">Poste</label></th><td><input class="form-control" id="${newFieldName}-poste" name="${newFieldName}-poste" type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-service">Service</label></th><td><input class="form-control" id="${newFieldName}-service" name="${newFieldName}-service" type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-origine">Origine</label></th><td><input class="form-control" id="${newFieldName}-origine" name="${newFieldName}-origine" type="text" value=""></td></tr>
<tr><th><label for="${newFieldName}-notes">Notes</label></th><td><input class="form-control" id="${newFieldName}-notes" name="${newFieldName}-notes" type="text" value=""></td></tr>
</table>
<input id="${newFieldName}-csrf_token" name="${newFieldName}-csrf_token" type="hidden" value=${csrf_token}>
<div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer ce correspondant</div>
</li>
`); `);
}); });
} }

View File

@ -5,7 +5,7 @@
{% block app_content %} {% block app_content %}
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
<br> <br>
<div>{{ info_message }}</div> <div style="color:red;">{{ info_message }}</div>
<br> <br>
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">

View File

@ -9,21 +9,7 @@
{% endblock %} {% endblock %}
{% block app_content %} {% block app_content %}
<div class="container"> <div class="container" style="margin-bottom: 10px;">
<ul class="breadcrumbs">
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
</li>
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise_id) }}" class="breadcrumbs_link">Fiche entreprise</a>
</li>
<li class="breadcrumbs_item">
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Contacts</a>
</li>
</ul>
</div>
<div class="container" style="margin-bottom: 10px;">
<h1>Liste des contacts</h1> <h1>Liste des contacts</h1>
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
<a class="btn btn-primary" style="margin-bottom:10px;" href="{{ url_for('entreprises.add_contact', id=entreprise_id) }}">Ajouter contact</a> <a class="btn btn-primary" style="margin-bottom:10px;" href="{{ url_for('entreprises.add_contact', id=entreprise_id) }}">Ajouter contact</a>

View File

@ -22,6 +22,15 @@
</div> </div>
{% endif %} {% endif %}
<div class="container boutons">
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %}
<a class="btn btn-default" href="{{ url_for('entreprises.import_correspondants') }}">Importer des correspondants</a>
{% endif %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and correspondants %}
<a class="btn btn-default" href="{{ url_for('entreprises.export_correspondants') }}">Exporter la liste des correspondants</a>
{% endif %}
</div>
<div class="container" style="margin-bottom: 10px;"> <div class="container" style="margin-bottom: 10px;">
<h1>Liste des correspondants</h1> <h1>Liste des correspondants</h1>
<table id="table-correspondants"> <table id="table-correspondants">
@ -45,7 +54,7 @@
<td>{{ correspondant[0].mail }}</td> <td>{{ correspondant[0].mail }}</td>
<td>{{ correspondant[0].poste}}</td> <td>{{ correspondant[0].poste}}</td>
<td>{{ correspondant[0].service}}</td> <td>{{ correspondant[0].service}}</td>
<td><a href="{{ url_for('entreprises.fiche_entreprise', id=correspondant[1].entreprise_id) }}">{{ correspondant[1].nom }}</a></td> <td><a href="{{ url_for('entreprises.fiche_entreprise', id=correspondant[1].id) }}">{{ correspondant[1].nom }}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -27,22 +27,15 @@
<a class="btn btn-default" href="{{ url_for('entreprises.add_entreprise') }}">Ajouter une entreprise</a> <a class="btn btn-default" href="{{ url_for('entreprises.add_entreprise') }}">Ajouter une entreprise</a>
{% endif %} {% endif %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %}
<a class="btn btn-default" href="{{ url_for('entreprises.import_donnees') }}">Importer des données</a> <a class="btn btn-default" href="{{ url_for('entreprises.import_entreprises') }}">Importer des entreprises</a>
{% endif %} {% endif %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and entreprises %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and entreprises %}
<a class="btn btn-default" href="{{ url_for('entreprises.export_donnees') }}">Exporter des données</a> <a class="btn btn-default" href="{{ url_for('entreprises.export_entreprises') }}">Exporter la liste des entreprises</a>
{% endif %} {% endif %}
</div> </div>
<div class="container" style="margin-bottom: 10px;"> <div class="container" style="margin-bottom: 10px;">
<h1>Liste des entreprises</h1> <h1>Liste des entreprises</h1>
{% if form %}
<form id="form-entreprise-filter" method="POST" action="">
{{ form.hidden_tag() }}
<input id="active" name="active" type="checkbox" onChange="form.submit()" {% if checked[0] %} checked {% endif %}> {{ form.active.label }}
<input id="association" name="association" type="checkbox" onChange="form.submit()" {% if checked[1] %} checked {% endif %}> {{ form.association.label }}
</form>
{% endif %}
<table id="table-entreprises"> <table id="table-entreprises">
<thead> <thead>
<tr> <tr>
@ -60,7 +53,7 @@
<tbody> <tbody>
{% for entreprise in entreprises %} {% for entreprise in entreprises %}
<tr> <tr>
<td><a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}" {% if not entreprise.active %} style="color:red" {% endif %}>{{ entreprise.siret }}</a></td> <td><a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}">{{ entreprise.siret }}</a></td>
<td>{{ entreprise.nom }}</td> <td>{{ entreprise.nom }}</td>
<td>{{ entreprise.adresse }}</td> <td>{{ entreprise.adresse }}</td>
<td>{{ entreprise.codepostal }}</td> <td>{{ entreprise.codepostal }}</td>
@ -74,11 +67,7 @@
</a> </a>
<ul class="dropdown-menu pull-left"> <ul class="dropdown-menu pull-left">
<li><a href="{{ url_for('entreprises.edit_entreprise', id=entreprise.id) }}">Modifier</a></li> <li><a href="{{ url_for('entreprises.edit_entreprise', id=entreprise.id) }}">Modifier</a></li>
{% if entreprise.active %}
<li><a href="{{ url_for('entreprises.fiche_entreprise_desactiver', id=entreprise.id)}}" style="color:red">Désactiver</a></li> <li><a href="{{ url_for('entreprises.fiche_entreprise_desactiver', id=entreprise.id)}}" style="color:red">Désactiver</a></li>
{% else %}
<li><a href="{{ url_for('entreprises.fiche_entreprise_activer', id=entreprise.id)}}" style="color:lightgreen">Activer</a></li>
{% endif %}
</ul> </ul>
</div> </div>
</td> </td>

View File

@ -18,9 +18,13 @@
</p> </p>
<form method="POST" action="" novalidate> <form method="POST" action="" novalidate>
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
{{ form.responsables.label }} {{ form.responsables.label }}<br>
{% for error in form.responsables.errors %} {% for subfield in form.responsables %}
<p class="help-block form-error">{{ error }}</p> {% if subfield.errors %}
{% for error in subfield.errors %}
<p class="help-block form-error">{{ error }}</p>
{% endfor %}
{% endif %}
{% endfor %} {% endfor %}
{{ form.responsables }} {{ form.responsables }}
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px;">
@ -67,11 +71,7 @@
} }
let newFieldName = `responsables-${Math.max(...responsableInputIds) + 1}`; let newFieldName = `responsables-${Math.max(...responsableInputIds) + 1}`;
allResponsablesFieldWrapper.insertAdjacentHTML('beforeend',` allResponsablesFieldWrapper.insertAdjacentHTML('beforeend',`
<li> <li><label for="${newFieldName}">Responsable (*)</label><input class="form-control" id="${newFieldName}" name="${newFieldName}" type="text" value="" placeholder="Tapez le nom du responsable de formation"><div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer</div></li>
<label for="${newFieldName}">Responsable (*)</label>
<input class="form-control" id="${newFieldName}" name="${newFieldName}" type="text" value="" placeholder="Tapez le nom du responsable de formation">
<div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer</div>
</li>
`); `);
var as_r = new bsn.AutoSuggest(newFieldName, responsables_options); var as_r = new bsn.AutoSuggest(newFieldName, responsables_options);
}); });

View File

@ -9,17 +9,6 @@
{% endblock %} {% endblock %}
{% block app_content %} {% block app_content %}
<div class="container">
<ul class="breadcrumbs">
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
</li>
<li class="breadcrumbs_item">
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Fiche entreprise</a>
</li>
</ul>
</div>
{% if logs %} {% if logs %}
<div class="container"> <div class="container">
<h3>Dernières opérations sur cette fiche <a href="{{ url_for('entreprises.logs_entreprise', id=entreprise.id) }}">Voir tout</a></h3> <h3>Dernières opérations sur cette fiche <a href="{{ url_for('entreprises.logs_entreprise', id=entreprise.id) }}">Voir tout</a></h3>
@ -37,15 +26,6 @@
<div class="container fiche-entreprise"> <div class="container fiche-entreprise">
<h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2> <h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2>
{% if not entreprise.active %}
<div class="info-active">
La fiche entreprise est désactivée<br>
{% if entreprise.notes_active != "" %}
Notes : {{ entreprise.notes_active }}
{% endif %}
</div>
{% endif %}
<div class="entreprise"> <div class="entreprise">
<div> <div>
SIRET : {{ entreprise.siret }}<br> SIRET : {{ entreprise.siret }}<br>
@ -53,41 +33,14 @@
Adresse : {{ entreprise.adresse }}<br> Adresse : {{ entreprise.adresse }}<br>
Code postal : {{ entreprise.codepostal }}<br> Code postal : {{ entreprise.codepostal }}<br>
Ville : {{ entreprise.ville }}<br> Ville : {{ entreprise.ville }}<br>
Pays : {{ entreprise.pays }}<br> Pays : {{ entreprise.pays }}
{% if entreprise.association %}
Association
{% endif %}
</div> </div>
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
<div>
Taxe d'apprentissage<br>
<a class="btn btn-primary" href="{{ url_for('entreprises.add_taxe_apprentissage', id=entreprise.id) }}">Ajouter taxe apprentissage</a>
<div class="taxe-apprentissage">
<ul id="liste-taxes-apprentissages">
{% if not taxes|check_taxe_now %}
<li>année actuelle : non versée</li>
{% endif %}
{% for taxe in taxes %}
<li>
<a href="{{ url_for('entreprises.delete_taxe_apprentissage', id_entreprise=entreprise.id, id_taxe=taxe.id) }}"><img title="Supprimer taxe d'apprentissage" alt="supprimer" width="10" height="9" border="0" src="/ScoDoc/static/icons/delete_small_img.png" /></a>
<a href="{{ url_for('entreprises.edit_taxe_apprentissage', id_entreprise=entreprise.id, id_taxe=taxe.id) }}">{{ taxe.annee }}</a> : {{ taxe.montant }} euros {% if taxe.notes %}- {{ taxe.notes}} {% endif %}
</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
</div> </div>
<div> <div>
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_entreprise', id=entreprise.id) }}">Modifier</a> <a class="btn btn-primary" href="{{ url_for('entreprises.edit_entreprise', id=entreprise.id) }}">Modifier</a>
{% if entreprise.active %}
<a class="btn btn-danger" href="{{ url_for('entreprises.fiche_entreprise_desactiver', id=entreprise.id) }}">Désactiver</a> <a class="btn btn-danger" href="{{ url_for('entreprises.fiche_entreprise_desactiver', id=entreprise.id) }}">Désactiver</a>
{% else %}
<a class="btn btn-success" href="{{ url_for('entreprises.fiche_entreprise_activer', id=entreprise.id) }}">Activer</a>
{% endif %}
<a class="btn btn-primary" href="{{ url_for('entreprises.add_site', id=entreprise.id) }}">Ajouter site</a> <a class="btn btn-primary" href="{{ url_for('entreprises.add_site', id=entreprise.id) }}">Ajouter site</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_offre', id=entreprise.id) }}">Ajouter offre</a>
{% endif %} {% endif %}
@ -108,10 +61,7 @@
Ville : {{ site.ville }}<br> Ville : {{ site.ville }}<br>
Pays : {{ site.pays }} Pays : {{ site.pays }}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
<div> <br><a class="btn btn-primary" href="{{ url_for('entreprises.add_correspondant', id_entreprise=entreprise.id, id_site=site.id) }}">Ajouter correspondant</a>
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_site', id_entreprise=entreprise.id, id_site=site.id) }}">Modifier</a>
<a class="btn btn-primary" href="{{ url_for('entreprises.add_correspondant', id_entreprise=entreprise.id, id_site=site.id) }}">Ajouter correspondant</a>
</div>
{% endif %} {% endif %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
{% for correspondant in site.correspondants %} {% for correspondant in site.correspondants %}
@ -161,7 +111,7 @@
<td>{{ data[0].date_fin.strftime('%d/%m/%Y') }}</td> <td>{{ data[0].date_fin.strftime('%d/%m/%Y') }}</td>
<td>{{ (data[0].date_fin-data[0].date_debut).days//7 }} semaines</td> <td>{{ (data[0].date_fin-data[0].date_debut).days//7 }} semaines</td>
<td>{{ data[0].type_offre }}</td> <td>{{ data[0].type_offre }}</td>
<td><a href="{{ url_for('scolar.ficheEtud', scodoc_dept=data[1].dept_id|get_dept_acronym, etudid=data[0].etudid) }}">{{ data[1].nom|format_nom }} {{ data[1].prenom|format_prenom }}</a></td> <td>{{ data[1].nom|format_nom }} {{ data[1].prenom|format_prenom }}</td>
<td>{% if data[0].formation_text %}{{ data[0].formation_text }}{% endif %}</td> <td>{% if data[0].formation_text %}{{ data[0].formation_text }}{% endif %}</td>
<td>{{ data[0].notes }}</td> <td>{{ data[0].notes }}</td>
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}

View File

@ -12,58 +12,35 @@
Adresse : {{ entreprise.adresse }}<br> Adresse : {{ entreprise.adresse }}<br>
Code postal : {{ entreprise.codepostal }}<br> Code postal : {{ entreprise.codepostal }}<br>
Ville : {{ entreprise.ville }}<br> Ville : {{ entreprise.ville }}<br>
Pays : {{ entreprise.pays }}<br> Pays : {{ entreprise.pays }}
{% if entreprise.association %}
Association
{% endif %}
</div> </div>
</div> </div>
<div class="sites-et-offres"> {% if correspondants %}
{% if sites %} <div>
{% for correspondant in correspondants %}
<div> <div>
<h3>Sites</h3> <h3>Correspondant</h3>
{% for site in sites %} <div class="correspondant">
<div class="site"> Nom : {{ correspondant.nom }}<br>
Nom : {{ site.nom }}<br> Prénom : {{ correspondant.prenom }}<br>
Adresse : {{ site.adresse }}<br> {% if correspondant.telephone %}
Code postal : {{ site.codepostal }}<br> Téléphone : {{ correspondant.telephone }}<br>
Ville : {{ site.ville }}<br> {% endif %}
Pays : {{ site.pays }} {% if correspondant.mail %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %} Mail : {{ correspondant.mail }}<br>
{% for correspondant in site.correspondants %} {% endif %}
<div class="correspondant"> {% if correspondant.poste %}
<div> Poste : {{ correspondant.poste }}<br>
Civilité : {{ correspondant.civilite|get_civilité }}<br> {% endif %}
Nom : {{ correspondant.nom }}<br> {% if correspondant.service %}
Prénom : {{ correspondant.prenom }}<br> Service : {{ correspondant.service }}<br>
{% if correspondant.telephone %}
Téléphone : {{ correspondant.telephone }}<br>
{% endif %}
{% if correspondant.mail %}
Mail : {{ correspondant.mail }}<br>
{% endif %}
{% if correspondant.poste %}
Poste : {{ correspondant.poste }}<br>
{% endif %}
{% if correspondant.service %}
Service : {{ correspondant.service }}<br>
{% endif %}
{% if correspondant.origine %}
Origine : {{ correspondant.origine }}<br>
{% endif %}
{% if correspondant.notes %}
Notes : {{ correspondant.notes }}<br>
{% endif %}
</div>
</div>
{% endfor %}
{% endif %} {% endif %}
</div> </div>
{% endfor %}
</div> </div>
{% endif %} {% endfor %}
</div> </div>
{% endif %}
<div> <div>
<a class="btn btn-success" href="{{ url_for('entreprises.validate_entreprise', id=entreprise.id) }}">Valider</a> <a class="btn btn-success" href="{{ url_for('entreprises.validate_entreprise', id=entreprise.id) }}">Valider</a>

View File

@ -0,0 +1,72 @@
{# -*- mode: jinja-html -*- #}
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block styles %}
{{super()}}
{% endblock %}
{% block app_content %}
<h1>Importation correspondants</h1>
<br>
<div>
<a href="{{ url_for('entreprises.get_import_correspondants_file_sample') }}">Obtenir la feuille excel à remplir</a>
</div>
<br>
<div class="row">
<div class="col-md-4">
<p>
(*) champs requis
</p>
{{ wtf.quick_form(form, novalidate=True) }}
</div>
</div>
{% if not correspondants_import %}
<table class="table">
<thead><tr><td><b>Attribut</b></td><td><b>Type</b></td><td><b>Description</b></td></tr></thead>
<tr><td>civilite</td><td>text</td><td>civilite du correspondant (H ou F)</td></tr>
<tr><td>nom</td><td>text</td><td>nom du correspondant</td></tr>
<tr><td>prenom</td><td>text</td><td>prenom du correspondant</td></tr>
<tr><td>telephone</td><td>text</td><td>telephone du correspondant</td></tr>
<tr><td>mail</td><td>text</td><td>mail du correspondant</td></tr>
<tr><td>poste</td><td>text</td><td>poste du correspondant</td></tr>
<tr><td>service</td><td>text</td><td>service dans lequel travaille le correspondant</td></tr>
<tr><td>origine</td><td>text</td><td>origine du correspondant</td></tr>
<tr><td>notes</td><td>text</td><td>notes sur le correspondant</td></tr>
<tr><td>entreprise_siret</td><td>text</td><td>SIRET de l'entreprise</td></tr>
</table>
{% endif %}
{% if correspondants_import %}
<br><div>Importation de {{ correspondants_import|length }} correspondant(s)</div>
{% for correspondant in correspondants_import %}
<div class="correspondant">
<div>
Civilité : {{ correspondant.civilite|get_civilité }}<br>
Nom : {{ correspondant.nom }}<br>
Prénom : {{ correspondant.prenom }}<br>
{% if correspondant.telephone %}
Téléphone : {{ correspondant.telephone }}<br>
{% endif %}
{% if correspondant.mail %}
Mail : {{ correspondant.mail }}<br>
{% endif %}
{% if correspondant.poste %}
Poste : {{ correspondant.poste }}<br>
{% endif %}
{% if correspondant.service %}
Service : {{ correspondant.service }}<br>
{% endif %}
{% if correspondant.origine %}
Origine : {{ correspondant.origine }}<br>
{% endif %}
{% if correspondant.notes %}
Notes : {{ correspondant.notes }}<br>
{% endif %}
<a href="{{ url_for('entreprises.fiche_entreprise', id=correspondant.entreprise_id )}}" target="_blank">lien vers l'entreprise</a>
</div>
</div>
{% endfor %}
{% endif %}
{% endblock %}

View File

@ -1,149 +0,0 @@
{# -*- mode: jinja-html -*- #}
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block styles %}
{{super()}}
{% endblock %}
{% block app_content %}
<div class="container">
<ul class="breadcrumbs">
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
</li>
<li class="breadcrumbs_item">
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Importation données</a>
</li>
</ul>
</div>
<div class="container">
<h1>{{ title }}</h1>
<br>
<div>
<a href="{{ url_for('entreprises.get_import_donnees_file_sample') }}">Obtenir la feuille excel à remplir</a>
</div>
<br>
<div class="row">
<div class="col-md-4">
<p>
(*) champs requis
</p>
{{ wtf.quick_form(form, novalidate=True) }}
</div>
</div>
{% if not entreprises_import and not sites_import and not correspondants_import %}
<div>Feuille Entreprises</div>
<table class="table">
<thead><tr><td><b>Attribut</b></td><td><b>Type</b></td><td><b>Description</b></td></tr></thead>
<tr><td>siret (*)</td><td>text</td><td>siret de l'entreprise</td></tr>
<tr><td>nom_entreprise (*)</td><td>text</td><td>nom de l'entreprise</td></tr>
<tr><td>adresse (*)</td><td>text</td><td>adresse de l'entreprise</td></tr>
<tr><td>ville (*)</td><td>text</td><td>ville de l'entreprise</td></tr>
<tr><td>code_postal (*)</td><td>text</td><td>code postal de l'entreprise</td></tr>
<tr><td>pays</td><td>text</td><td>pays de l'entreprise</td></tr>
</table>
<div>Feuille Sites</div>
<table class="table">
<thead><tr><td><b>Attribut</b></td><td><b>Type</b></td><td><b>Description</b></td></tr></thead>
<tr><td>siret_entreprise (*)</td><td>text</td><td>siret de l'entreprise</td></tr>
<tr><td>id_site (*)</td><td>text</td><td>id du site (ne rien remplir pour créer un site)</td></tr>
<tr><td>nom_site (*)</td><td>text</td><td>nom du site</td></tr>
<tr><td>adresse (*)</td><td>text</td><td>adresse du site</td></tr>
<tr><td>ville (*)</td><td>text</td><td>ville du site</td></tr>
<tr><td>code_postal (*)</td><td>text</td><td>code postal du site</td></tr>
<tr><td>pays (*)</td><td>text</td><td>pays du site</td></tr>
</table>
<div>Feuille Correspondants (à utiliser pour les modifications)</div>
<table class="table">
<thead><tr><td><b>Attribut</b></td><td><b>Type</b></td><td><b>Description</b></td></tr></thead>
<tr><td>civilite (*)</td><td>text</td><td>civilite du correspondant (H ou F)</td></tr>
<tr><td>nom (*)</td><td>text</td><td>nom du correspondant</td></tr>
<tr><td>prenom (*)</td><td>text</td><td>prenom du correspondant</td></tr>
<tr><td>telephone (*)</td><td>text</td><td>telephone du correspondant</td></tr>
<tr><td>mail (*)</td><td>text</td><td>mail du correspondant</td></tr>
<tr><td>poste</td><td>text</td><td>poste du correspondant</td></tr>
<tr><td>service</td><td>text</td><td>service dans lequel travaille le correspondant</td></tr>
<tr><td>origine</td><td>text</td><td>origine du correspondant</td></tr>
<tr><td>notes</td><td>text</td><td>notes sur le correspondant</td></tr>
<tr><td>nom_site</td><td>text</td><td>nom du site lié au correspondant</td></tr>
</table>
{% endif %}
{% if entreprises_import %}
<br><div>Importation de {{ entreprises_import|length }} entreprise(s)</div>
{% for entreprise in entreprises_import %}
<div class="entreprise">
<div>
SIRET : {{ entreprise.siret }}<br>
Nom : {{ entreprise.nom }}<br>
Adresse : {{ entreprise.adresse }}<br>
Code postal : {{ entreprise.codepostal }}<br>
Ville : {{ entreprise.ville }}<br>
Pays : {{ entreprise.pays }}<br>
<a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}" target="_blank">Fiche entreprise</a>
</div>
{% for site in entreprise.sites %}
<div class="site">
Nom : {{ site.nom }}<br>
Adresse : {{ site.adresse }}<br>
Code postal : {{ site.codepostal }}<br>
Ville : {{ site.ville }}<br>
Pays : {{ site.pays }}
</div>
{% endfor %}
</div>
{% endfor %}
{% endif %}
{% if sites_import %}
<br><div>Importation de {{ sites_import|length }} site(s)</div>
{% for site in sites_import %}
<div class="site">
Nom : {{ site.nom }}<br>
Adresse : {{ site.adresse }}<br>
Code postal : {{ site.codepostal }}<br>
Ville : {{ site.ville }}<br>
Pays : {{ site.pays }}<br>
<a href="{{ url_for('entreprises.fiche_entreprise', id=site.entreprise_id) }}" target="_blank">Fiche entreprise</a>
</div>
{% endfor %}
{% endif %}
{% if correspondants_import %}
<br><div>Importation de {{ correspondants_import|length }} correspondant(s)</div>
{% for correspondant in correspondants_import %}
<div class="correspondant">
<div>
Civilité : {{ correspondant.civilite|get_civilité }}<br>
Nom : {{ correspondant.nom }}<br>
Prénom : {{ correspondant.prenom }}<br>
{% if correspondant.telephone %}
Téléphone : {{ correspondant.telephone }}<br>
{% endif %}
{% if correspondant.mail %}
Mail : {{ correspondant.mail }}<br>
{% endif %}
{% if correspondant.poste %}
Poste : {{ correspondant.poste }}<br>
{% endif %}
{% if correspondant.service %}
Service : {{ correspondant.service }}<br>
{% endif %}
{% if correspondant.origine %}
Origine : {{ correspondant.origine }}<br>
{% endif %}
{% if correspondant.notes %}
Notes : {{ correspondant.notes }}<br>
{% endif %}
<a href="{{ url_for('entreprises.fiche_entreprise', id=correspondant.entreprise_id) }}" target="_blank">Fiche entreprise</a>
</div>
</div>
{% endfor %}
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,52 @@
{# -*- mode: jinja-html -*- #}
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block styles %}
{{super()}}
{% endblock %}
{% block app_content %}
<h1>Importation entreprises</h1>
<br>
<div>
<a href="{{ url_for('entreprises.get_import_entreprises_file_sample') }}">Obtenir la feuille excel à remplir</a>
</div>
<br>
<div class="row">
<div class="col-md-4">
<p>
(*) champs requis
</p>
{{ wtf.quick_form(form, novalidate=True) }}
</div>
</div>
{% if not entreprises_import %}
<table class="table">
<thead><tr><td><b>Attribut</b></td><td><b>Type</b></td><td><b>Description</b></td></tr></thead>
<tr><td>siret</td><td>text</td><td>siret de l'entreprise</td></tr>
<tr><td>nom_entreprise</td><td>text</td><td>nom de l'entreprise</td></tr>
<tr><td>adresse</td><td>text</td><td>adresse de l'entreprise</td></tr>
<tr><td>ville</td><td>text</td><td>ville de l'entreprise</td></tr>
<tr><td>code_postal</td><td>text</td><td>code postal de l'entreprise</td></tr>
<tr><td>pays</td><td>text</td><td>pays de l'entreprise</td></tr>
</table>
{% endif %}
{% if entreprises_import %}
<br><div>Importation de {{ entreprises_import|length }} entreprise(s)</div>
{% for entreprise in entreprises_import %}
<div class="entreprise">
<div>
SIRET : {{ entreprise.siret }}<br>
Nom : {{ entreprise.nom }}<br>
Adresse : {{ entreprise.adresse }}<br>
Code postal : {{ entreprise.codepostal }}<br>
Ville : {{ entreprise.ville }}<br>
Pays : {{ entreprise.pays }}
</div>
</div>
{% endfor %}
{% endif %}
{% endblock %}

View File

@ -2,17 +2,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block app_content %} {% block app_content %}
<div class="container">
<ul class="breadcrumbs">
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
</li>
<li class="breadcrumbs_item">
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Dernières opérations</a>
</li>
</ul>
</div>
<div class="container"> <div class="container">
<h3>Dernières opérations</h3> <h3>Dernières opérations</h3>
{% if logs.items %} {% if logs.items %}

View File

@ -2,20 +2,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block app_content %} {% block app_content %}
<div class="container">
<ul class="breadcrumbs">
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
</li>
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}" class="breadcrumbs_link">Fiche entreprise</a>
</li>
<li class="breadcrumbs_item">
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Dernières opérations</a>
</li>
</ul>
</div>
<div class="container"> <div class="container">
<h3>Dernières opérations - {{ entreprise.nom }}</h3> <h3>Dernières opérations - {{ entreprise.nom }}</h3>
{% if logs.items %} {% if logs.items %}

View File

@ -1,16 +1,14 @@
{# -*- mode: jinja-html -*- #} {# -*- mode: jinja-html -*- #}
<div class="container"> <nav class="nav-entreprise">
<nav class="nav-entreprise"> <ul>
<ul> <li><a href="{{ url_for('entreprises.index') }}">Entreprises</a></li>
<li><a href="{{ url_for('entreprises.index') }}">Entreprises</a></li> {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %} <li><a href="{{ url_for('entreprises.correspondants') }}">Correspondants</a></li>
<li><a href="{{ url_for('entreprises.correspondants') }}">Correspondants</a></li> {% endif %}
{% endif %} <li><a href="{{ url_for('entreprises.offres_recues') }}">Offres reçues</a></li>
<li><a href="{{ url_for('entreprises.offres_recues') }}">Offres reçues</a></li> {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesValidate, None) %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesValidate, None) %} <li><a href="{{ url_for('entreprises.validation') }}">Entreprises à valider</a></li>
<li><a href="{{ url_for('entreprises.validation') }}">Entreprises à valider</a></li> <li><a href="{{ url_for('entreprises.preferences') }}">Préférences</a></li>
<li><a href="{{ url_for('entreprises.preferences') }}">Préférences</a></li> {% endif %}
{% endif %} </ul>
</ul> </nav>
</nav>
</div>

View File

@ -2,20 +2,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block app_content %} {% block app_content %}
<div class="container">
<ul class="breadcrumbs">
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
</li>
<li class="breadcrumbs_item">
<a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}" class="breadcrumbs_link">Fiche entreprise</a>
</li>
<li class="breadcrumbs_item">
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Offres expirées</a>
</li>
</ul>
</div>
<div class="container"> <div class="container">
<h1>Offres expirées - {{ entreprise.nom }}</h1> <h1>Offres expirées - {{ entreprise.nom }}</h1>
{% if offres_expirees %} {% if offres_expirees %}

View File

@ -5,13 +5,11 @@
{% block app_content %} {% block app_content %}
{% include 'entreprises/nav.html' %} {% include 'entreprises/nav.html' %}
<div class="container"> <h1>Préférences module gestion entreprises</h1>
<h1>Préférences module gestion entreprises</h1> <br>
<br> <div class="row">
<div class="row"> <div class="col-md-4">
<div class="col-md-4"> {{ wtf.quick_form(form, novalidate=True) }}
{{ wtf.quick_form(form, novalidate=True) }}
</div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,76 +0,0 @@
"""ajout taxe apprentissage, association, changement historique
Revision ID: 0b337376e9f7
Revises: ee21c76c8183
Create Date: 2022-07-04 21:10:53.946385
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = "0b337376e9f7"
down_revision = "ee21c76c8183"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"are_historique",
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("entreprise_id", sa.Integer(), nullable=True),
sa.Column("object", sa.Text(), nullable=True),
sa.Column("object_id", sa.Integer(), nullable=True),
sa.Column("text", sa.Text(), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"are_taxe_apprentissage",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("entreprise_id", sa.Integer(), nullable=True),
sa.Column("annee", sa.Integer(), nullable=True),
sa.Column("montant", sa.Integer(), nullable=True),
sa.Column("notes", sa.Text(), nullable=True),
sa.ForeignKeyConstraint(
["entreprise_id"], ["are_entreprises.id"], ondelete="cascade"
),
sa.PrimaryKeyConstraint("id"),
)
op.drop_table("are_logs")
op.add_column(
"are_entreprises", sa.Column("association", sa.Boolean(), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("are_entreprises", "association")
op.create_table(
"are_logs",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column(
"date",
postgresql.TIMESTAMP(timezone=True),
server_default=sa.text("now()"),
autoincrement=False,
nullable=True,
),
sa.Column("authenticated_user", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("object", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("text", sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint("id", name="are_logs_pkey"),
)
op.drop_table("are_taxe_apprentissage")
op.drop_table("are_historique")
# ### end Alembic commands ###