Merge branch 'master' of https://scodoc.org/git/viennet/ScoDoc into situation_but
This commit is contained in:
commit
c9f399d9f7
3
.gitignore
vendored
3
.gitignore
vendored
@ -173,3 +173,6 @@ Thumbs.db
|
||||
.idea/
|
||||
|
||||
copy
|
||||
|
||||
# Symlinks static ScoDoc
|
||||
app/static/links/[0-9]*.*[0-9]
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""entreprises.__init__
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from flask import Blueprint
|
||||
from app.scodoc import sco_etud
|
||||
from app.auth.models import User
|
||||
@ -47,4 +48,12 @@ def get_civilité(civ):
|
||||
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
|
||||
|
@ -30,6 +30,7 @@ import re
|
||||
import requests
|
||||
import glob
|
||||
|
||||
from flask import flash
|
||||
from flask_login import current_user
|
||||
|
||||
from app.entreprises.models import (
|
||||
@ -38,14 +39,61 @@ from app.entreprises.models import (
|
||||
EntrepriseOffre,
|
||||
EntrepriseOffreDepartement,
|
||||
EntreprisePreferences,
|
||||
EntrepriseSite,
|
||||
EntrepriseHistorique,
|
||||
)
|
||||
|
||||
from app import email
|
||||
from app import email, db
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc import sco_excel
|
||||
from app.models import Departement
|
||||
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():
|
||||
"""
|
||||
Retourne une liste contenant les l'id des départements des roles de l'utilisateur courant
|
||||
@ -58,7 +106,7 @@ def get_depts():
|
||||
return depts
|
||||
|
||||
|
||||
def get_dept_id_by_acronym(acronym):
|
||||
def get_dept_id_by_acronym(acronym: str):
|
||||
"""
|
||||
Retourne l'id d'un departement a l'aide de son acronym
|
||||
"""
|
||||
@ -68,7 +116,14 @@ def get_dept_id_by_acronym(acronym):
|
||||
return None
|
||||
|
||||
|
||||
def check_offre_depts(depts, offre_depts):
|
||||
def get_dept_acronym_by_id(id: int):
|
||||
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
|
||||
"""
|
||||
@ -107,7 +162,7 @@ def get_offre_files_and_depts(offre: EntrepriseOffre, depts: list):
|
||||
return None
|
||||
|
||||
|
||||
def send_email_notifications_entreprise(subject, entreprise: Entreprise):
|
||||
def send_email_notifications_entreprise(subject: str, entreprise: Entreprise):
|
||||
txt = [
|
||||
"Une entreprise est en attente de validation",
|
||||
"Entreprise:",
|
||||
@ -128,69 +183,168 @@ def send_email_notifications_entreprise(subject, entreprise: Entreprise):
|
||||
return txt
|
||||
|
||||
|
||||
def verif_correspondant_data(correspondant_data):
|
||||
def get_excel_book_are(export: bool = False):
|
||||
"""
|
||||
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
|
||||
Retourne un Excel avec les 3 feuilles "Entreprises", "Sites" et "Correspondants"
|
||||
"""
|
||||
# champs obligatoires
|
||||
entreprises_titles = ENTREPRISES_KEYS[:]
|
||||
sites_titles = SITES_KEYS[:]
|
||||
correspondants_titles = CORRESPONDANTS_KEYS[:]
|
||||
wb = sco_excel.ScoExcelBook()
|
||||
ws1 = wb.create_sheet("Entreprises")
|
||||
ws1.append_row(
|
||||
[
|
||||
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
|
||||
l = list_to_dict(m)
|
||||
for entreprise_data in l:
|
||||
ligne += 1
|
||||
entreprise_data["siret"] = entreprise_data["siret"].replace(" ", "")
|
||||
if (
|
||||
correspondant_data[0].strip() == ""
|
||||
or correspondant_data[1].strip() == ""
|
||||
or correspondant_data[2].strip() == ""
|
||||
or correspondant_data[9].strip() == ""
|
||||
check_entreprise_import(entreprise_data)
|
||||
and entreprise_data["siret"] not in siret_list
|
||||
):
|
||||
return False
|
||||
|
||||
# civilite entre H ou F
|
||||
if correspondant_data[0].strip() not in ["H", "F"]:
|
||||
return False
|
||||
|
||||
# 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,
|
||||
siret_list.append(entreprise_data["siret"])
|
||||
entreprise = Entreprise.query.filter_by(
|
||||
siret=entreprise_data["siret"], visible=True
|
||||
).first()
|
||||
if correspondant is not None:
|
||||
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 (
|
||||
correspondant_data[3].strip() == "" and correspondant_data[4].strip() == ""
|
||||
): # 1 moyen de contact
|
||||
return False
|
||||
if len(entreprises_import) > 0:
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
text=f"Importation de {len(entreprises_import)} entreprise(s)",
|
||||
)
|
||||
db.session.add(log)
|
||||
|
||||
return True
|
||||
return entreprises_import
|
||||
|
||||
|
||||
def verif_entreprise_data(entreprise_data):
|
||||
def check_entreprise_import(entreprise_data):
|
||||
"""
|
||||
Verifie les données d'une ligne Excel (entreprise)
|
||||
"""
|
||||
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() == "":
|
||||
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():
|
||||
siret = entreprise_data[0].strip().replace(" ", "") # vérification sur le siret
|
||||
if re.match("^\d{14}$", siret) is None:
|
||||
return False
|
||||
try:
|
||||
@ -201,7 +355,210 @@ def verif_entreprise_data(entreprise_data):
|
||||
return False
|
||||
except requests.ConnectionError:
|
||||
return False
|
||||
entreprise = Entreprise.query.filter_by(siret=siret).first()
|
||||
if entreprise is not None:
|
||||
return True
|
||||
|
||||
|
||||
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 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
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
import re
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_wtf.file import FileField, FileAllowed, FileRequired
|
||||
@ -33,6 +34,7 @@ from markupsafe import Markup
|
||||
from sqlalchemy import text
|
||||
from wtforms import (
|
||||
StringField,
|
||||
IntegerField,
|
||||
SubmitField,
|
||||
TextAreaField,
|
||||
SelectField,
|
||||
@ -42,14 +44,23 @@ from wtforms import (
|
||||
BooleanField,
|
||||
FieldList,
|
||||
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 app.entreprises.models import (
|
||||
Entreprise,
|
||||
EntrepriseCorrespondant,
|
||||
EntreprisePreferences,
|
||||
EntrepriseSite,
|
||||
EntrepriseTaxeApprentissage,
|
||||
)
|
||||
from app.models import Identite, Departement
|
||||
from app.auth.models import User
|
||||
@ -69,11 +80,17 @@ def _build_string_field(label, required=True, render_kw=None):
|
||||
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):
|
||||
siret = _build_string_field(
|
||||
"SIRET (*)",
|
||||
render_kw={"placeholder": "Numéro composé de 14 chiffres"},
|
||||
)
|
||||
association = BooleanField("Association")
|
||||
nom_entreprise = _build_string_field("Nom de l'entreprise (*)")
|
||||
adresse = _build_string_field("Adresse de l'entreprise (*)")
|
||||
codepostal = _build_string_field("Code postal de l'entreprise (*)")
|
||||
@ -153,8 +170,8 @@ class EntrepriseCreationForm(FlaskForm):
|
||||
|
||||
|
||||
class EntrepriseModificationForm(FlaskForm):
|
||||
hidden_entreprise_siret = HiddenField()
|
||||
siret = StringField("SIRET (*)")
|
||||
association = BooleanField("Association")
|
||||
nom = _build_string_field("Nom de l'entreprise (*)")
|
||||
adresse = _build_string_field("Adresse (*)")
|
||||
codepostal = _build_string_field("Code postal (*)")
|
||||
@ -164,13 +181,11 @@ class EntrepriseModificationForm(FlaskForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.siret.render_kw = {
|
||||
"disabled": "",
|
||||
"value": self.hidden_entreprise_siret.data,
|
||||
}
|
||||
self.siret.render_kw = {"disabled": ""}
|
||||
|
||||
|
||||
class SiteCreationForm(FlaskForm):
|
||||
hidden_entreprise_id = HiddenField()
|
||||
nom = _build_string_field("Nom du site (*)")
|
||||
adresse = _build_string_field("Adresse (*)")
|
||||
codepostal = _build_string_field("Code postal (*)")
|
||||
@ -178,6 +193,49 @@ class SiteCreationForm(FlaskForm):
|
||||
pays = _build_string_field("Pays", required=False)
|
||||
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):
|
||||
widget = ListWidget(prefix_label=False)
|
||||
@ -214,7 +272,7 @@ class OffreCreationForm(FlaskForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.correspondant.choices = [
|
||||
self.correspondant.choices = [("", "")] + [
|
||||
(correspondant.id, f"{correspondant.nom} {correspondant.prenom}")
|
||||
for correspondant in EntrepriseCorrespondant.query.filter_by(
|
||||
entreprise_id=self.hidden_entreprise_id.data
|
||||
@ -260,7 +318,7 @@ class OffreModificationForm(FlaskForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.correspondant.choices = [
|
||||
self.correspondant.choices = [("", "")] + [
|
||||
(correspondant.id, f"{correspondant.nom} {correspondant.prenom}")
|
||||
for correspondant in EntrepriseCorrespondant.query.filter_by(
|
||||
entreprise_id=self.hidden_entreprise_id.data
|
||||
@ -290,8 +348,16 @@ class CorrespondantCreationForm(FlaskForm):
|
||||
validators=[DataRequired(message=CHAMP_REQUIS)],
|
||||
render_kw={"class": "form-control"},
|
||||
)
|
||||
nom = _build_string_field("Nom (*)", render_kw={"class": "form-control"})
|
||||
prenom = _build_string_field("Prénom (*)", render_kw={"class": "form-control"})
|
||||
nom = StringField(
|
||||
"Nom (*)",
|
||||
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(
|
||||
"Téléphone (*)", required=False, render_kw={"class": "form-control"}
|
||||
)
|
||||
@ -321,7 +387,6 @@ class CorrespondantCreationForm(FlaskForm):
|
||||
if not self.telephone.data and not self.mail.data:
|
||||
msg = "Saisir un moyen de contact (mail ou téléphone)"
|
||||
self.telephone.errors.append(msg)
|
||||
self.mail.errors.append(msg)
|
||||
validate = False
|
||||
|
||||
return validate
|
||||
@ -558,9 +623,75 @@ class StageApprentissageModificationForm(FlaskForm):
|
||||
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):
|
||||
responsables = FieldList(
|
||||
_build_string_field(
|
||||
StringField(
|
||||
"Responsable (*)",
|
||||
render_kw={
|
||||
"placeholder": "Tapez le nom du responsable de formation",
|
||||
@ -573,6 +704,8 @@ class EnvoiOffreForm(FlaskForm):
|
||||
|
||||
def validate(self):
|
||||
validate = True
|
||||
list_select = True
|
||||
|
||||
if not FlaskForm.validate(self):
|
||||
validate = False
|
||||
|
||||
@ -588,8 +721,12 @@ class EnvoiOffreForm(FlaskForm):
|
||||
.first()
|
||||
)
|
||||
if responsable is None:
|
||||
entry.errors.append("Champ incorrect (selectionnez dans la liste)")
|
||||
validate = False
|
||||
validate, list_select = False, False
|
||||
|
||||
if list_select is False:
|
||||
self.responsables.errors.append(
|
||||
"Champ incorrect (selectionnez dans la liste)"
|
||||
)
|
||||
|
||||
return validate
|
||||
|
||||
@ -611,7 +748,11 @@ class SuppressionConfirmationForm(FlaskForm):
|
||||
|
||||
class DesactivationConfirmationForm(FlaskForm):
|
||||
notes_active = TextAreaField("Notes sur la désactivation", validators=[Optional()])
|
||||
submit = SubmitField("Désactiver", render_kw=SUBMIT_MARGE)
|
||||
submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE)
|
||||
|
||||
|
||||
class ActivationConfirmationForm(FlaskForm):
|
||||
submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE)
|
||||
|
||||
|
||||
class ValidationConfirmationForm(FlaskForm):
|
||||
@ -633,6 +774,7 @@ class PreferencesForm(FlaskForm):
|
||||
mail_entreprise = StringField(
|
||||
"Mail notifications",
|
||||
validators=[Optional(), Email(message="Adresse e-mail invalide")],
|
||||
description="utilisé pour envoi mail notification application relations entreprises",
|
||||
)
|
||||
check_siret = BooleanField("Vérification SIRET")
|
||||
submit = SubmitField("Valider", render_kw=SUBMIT_MARGE)
|
||||
|
@ -10,6 +10,7 @@ class Entreprise(db.Model):
|
||||
codepostal = db.Column(db.Text)
|
||||
ville = db.Column(db.Text)
|
||||
pays = db.Column(db.Text)
|
||||
association = db.Column(db.Boolean, default=False)
|
||||
visible = db.Column(db.Boolean, default=False)
|
||||
active = db.Column(db.Boolean, default=True)
|
||||
notes_active = db.Column(db.Text)
|
||||
@ -36,6 +37,10 @@ class Entreprise(db.Model):
|
||||
"code_postal": self.codepostal,
|
||||
"ville": self.ville,
|
||||
"pays": self.pays,
|
||||
"association": self.association,
|
||||
"visible": self.visible,
|
||||
"active": self.active,
|
||||
"notes_active": self.notes_active,
|
||||
}
|
||||
|
||||
|
||||
@ -58,6 +63,18 @@ class EntrepriseSite(db.Model):
|
||||
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):
|
||||
__tablename__ = "are_correspondants"
|
||||
@ -77,8 +94,9 @@ class EntrepriseCorrespondant(db.Model):
|
||||
notes = db.Column(db.Text)
|
||||
|
||||
def to_dict(self):
|
||||
entreprise = Entreprise.query.filter_by(id=self.entreprise_id).first()
|
||||
site = EntrepriseSite.query.get_or_404(self.site_id)
|
||||
return {
|
||||
"id": self.id,
|
||||
"civilite": self.civilite,
|
||||
"nom": self.nom,
|
||||
"prenom": self.prenom,
|
||||
@ -88,7 +106,7 @@ class EntrepriseCorrespondant(db.Model):
|
||||
"service": self.service,
|
||||
"origine": self.origine,
|
||||
"notes": self.notes,
|
||||
"entreprise_siret": entreprise.siret,
|
||||
"nom_site": site.nom,
|
||||
}
|
||||
|
||||
|
||||
@ -131,12 +149,14 @@ class EntrepriseOffre(db.Model):
|
||||
}
|
||||
|
||||
|
||||
class EntrepriseLog(db.Model):
|
||||
__tablename__ = "are_logs"
|
||||
class EntrepriseHistorique(db.Model):
|
||||
__tablename__ = "are_historique"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||
authenticated_user = db.Column(db.Text)
|
||||
object = db.Column(db.Integer)
|
||||
entreprise_id = db.Column(db.Integer)
|
||||
object = db.Column(db.Text)
|
||||
object_id = db.Column(db.Integer)
|
||||
text = db.Column(db.Text)
|
||||
|
||||
|
||||
@ -155,6 +175,17 @@ class EntrepriseStageApprentissage(db.Model):
|
||||
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):
|
||||
__tablename__ = "are_envoi_offre"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
|
@ -12,11 +12,14 @@ from app.decorators import permission_required
|
||||
|
||||
from app.entreprises import LOGS_LEN
|
||||
from app.entreprises.forms import (
|
||||
ActivationConfirmationForm,
|
||||
CorrespondantsCreationForm,
|
||||
DesactivationConfirmationForm,
|
||||
EntrepriseCreationForm,
|
||||
EntrepriseModificationForm,
|
||||
EntreprisesFilterForm,
|
||||
SiteCreationForm,
|
||||
SiteModificationForm,
|
||||
SuppressionConfirmationForm,
|
||||
OffreCreationForm,
|
||||
OffreModificationForm,
|
||||
@ -27,6 +30,8 @@ from app.entreprises.forms import (
|
||||
StageApprentissageModificationForm,
|
||||
EnvoiOffreForm,
|
||||
AjoutFichierForm,
|
||||
TaxeApprentissageForm,
|
||||
TaxeApprentissageModificationForm,
|
||||
ValidationConfirmationForm,
|
||||
ImportForm,
|
||||
PreferencesForm,
|
||||
@ -36,13 +41,14 @@ from app.entreprises.models import (
|
||||
Entreprise,
|
||||
EntrepriseOffre,
|
||||
EntrepriseCorrespondant,
|
||||
EntrepriseLog,
|
||||
EntrepriseHistorique,
|
||||
EntrepriseContact,
|
||||
EntrepriseSite,
|
||||
EntrepriseStageApprentissage,
|
||||
EntrepriseEnvoiOffre,
|
||||
EntrepriseOffreDepartement,
|
||||
EntreprisePreferences,
|
||||
EntrepriseTaxeApprentissage,
|
||||
)
|
||||
from app.entreprises import app_relations_entreprises as are
|
||||
from app.models import Identite
|
||||
@ -52,18 +58,40 @@ from app.scodoc import sco_etud, sco_excel
|
||||
import app.scodoc.sco_utils as scu
|
||||
|
||||
from app import db
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy import text, sql
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
|
||||
@bp.route("/", methods=["GET"])
|
||||
@bp.route("/", methods=["GET", "POST"])
|
||||
@permission_required(Permission.RelationsEntreprisesView)
|
||||
def index():
|
||||
"""
|
||||
Permet d'afficher une page avec la liste des entreprises (visible) et une liste des dernières opérations
|
||||
"""
|
||||
entreprises = Entreprise.query.filter_by(visible=True, active=True)
|
||||
logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all()
|
||||
logs = (
|
||||
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(
|
||||
"entreprises/entreprises.html",
|
||||
title="Entreprises",
|
||||
@ -79,9 +107,9 @@ def logs():
|
||||
Permet d'afficher les logs (toutes les entreprises)
|
||||
"""
|
||||
page = request.args.get("page", 1, type=int)
|
||||
logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).paginate(
|
||||
page=page, per_page=20
|
||||
)
|
||||
logs = EntrepriseHistorique.query.order_by(
|
||||
EntrepriseHistorique.date.desc()
|
||||
).paginate(page=page, per_page=20)
|
||||
return render_template(
|
||||
"entreprises/logs.html",
|
||||
title="Logs",
|
||||
@ -110,11 +138,17 @@ def correspondants():
|
||||
Permet d'afficher une page avec la liste des correspondants des entreprises visibles et une liste des dernières opérations
|
||||
"""
|
||||
correspondants = (
|
||||
db.session.query(EntrepriseCorrespondant, Entreprise)
|
||||
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
|
||||
db.session.query(EntrepriseCorrespondant, EntrepriseSite)
|
||||
.join(EntrepriseSite, EntrepriseCorrespondant.site_id == EntrepriseSite.id)
|
||||
.join(Entreprise, EntrepriseSite.entreprise_id == Entreprise.id)
|
||||
.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(
|
||||
"entreprises/correspondants.html",
|
||||
title="Correspondants",
|
||||
@ -132,9 +166,9 @@ def fiche_entreprise(id):
|
||||
La fiche entreprise comporte les informations de l'entreprise, les correspondants de l'entreprise et
|
||||
les offres de l'entreprise.
|
||||
"""
|
||||
entreprise = Entreprise.query.filter_by(
|
||||
id=id, visible=True, active=True
|
||||
).first_or_404(description=f"fiche entreprise {id} inconnue")
|
||||
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
|
||||
description=f"fiche entreprise {id} inconnue"
|
||||
)
|
||||
offres_with_files = []
|
||||
depts = are.get_depts()
|
||||
for offre in entreprise.offres:
|
||||
@ -150,8 +184,8 @@ def fiche_entreprise(id):
|
||||
offres_with_files.append(offre_with_files)
|
||||
sites = entreprise.sites[:]
|
||||
logs = (
|
||||
EntrepriseLog.query.order_by(EntrepriseLog.date.desc())
|
||||
.filter_by(object=id)
|
||||
EntrepriseHistorique.query.order_by(EntrepriseHistorique.date.desc())
|
||||
.filter(EntrepriseHistorique.entreprise_id == id)
|
||||
.limit(LOGS_LEN)
|
||||
.all()
|
||||
)
|
||||
@ -162,6 +196,11 @@ def fiche_entreprise(id):
|
||||
.join(Identite, Identite.id == EntrepriseStageApprentissage.etudid)
|
||||
.all()
|
||||
)
|
||||
taxes = (
|
||||
EntrepriseTaxeApprentissage.query.filter_by(entreprise_id=id)
|
||||
.order_by(EntrepriseTaxeApprentissage.annee.desc())
|
||||
.all()
|
||||
)
|
||||
return render_template(
|
||||
"entreprises/fiche_entreprise.html",
|
||||
title="Fiche entreprise",
|
||||
@ -170,6 +209,7 @@ def fiche_entreprise(id):
|
||||
offres=offres_with_files,
|
||||
logs=logs,
|
||||
stages_apprentissages=stages_apprentissages,
|
||||
taxes=taxes,
|
||||
)
|
||||
|
||||
|
||||
@ -184,8 +224,8 @@ def logs_entreprise(id):
|
||||
description=f"logs fiche entreprise {id} inconnu"
|
||||
)
|
||||
logs = (
|
||||
EntrepriseLog.query.order_by(EntrepriseLog.date.desc())
|
||||
.filter_by(object=id)
|
||||
EntrepriseHistorique.query.order_by(EntrepriseHistorique.date.desc())
|
||||
.filter(EntrepriseHistorique.entreprise_id == entreprise.id)
|
||||
.paginate(page=page, per_page=20)
|
||||
)
|
||||
return render_template(
|
||||
@ -205,12 +245,12 @@ def fiche_entreprise_validation(id):
|
||||
entreprise = Entreprise.query.filter_by(id=id, visible=False).first_or_404(
|
||||
description=f"fiche entreprise (validation) {id} inconnue"
|
||||
)
|
||||
correspondants = entreprise.correspondants
|
||||
sites = entreprise.sites[:]
|
||||
return render_template(
|
||||
"entreprises/fiche_entreprise_validation.html",
|
||||
title="Validation fiche entreprise",
|
||||
entreprise=entreprise,
|
||||
correspondants=correspondants,
|
||||
sites=sites,
|
||||
)
|
||||
|
||||
|
||||
@ -290,6 +330,7 @@ def add_entreprise():
|
||||
entreprise = Entreprise(
|
||||
nom=form.nom_entreprise.data.strip(),
|
||||
siret=form.siret.data.strip(),
|
||||
association=form.association.data,
|
||||
adresse=form.adresse.data.strip(),
|
||||
codepostal=form.codepostal.data.strip(),
|
||||
ville=form.ville.data.strip(),
|
||||
@ -327,9 +368,10 @@ def add_entreprise():
|
||||
if current_user.has_permission(Permission.RelationsEntreprisesValidate, None):
|
||||
entreprise.visible = True
|
||||
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>"
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
text=f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom})",
|
||||
entreprise_id=entreprise.id,
|
||||
)
|
||||
db.session.add(log)
|
||||
db.session.commit()
|
||||
@ -360,51 +402,52 @@ def edit_entreprise(id):
|
||||
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
|
||||
description=f"entreprise {id} inconnue"
|
||||
)
|
||||
form = EntrepriseModificationForm(hidden_entreprise_siret=entreprise.siret)
|
||||
form = EntrepriseModificationForm(siret=entreprise.siret)
|
||||
if form.validate_on_submit():
|
||||
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{form.nom.data.strip()}</a>"
|
||||
if entreprise.nom != form.nom.data.strip():
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=entreprise.id,
|
||||
text=f"{nom_entreprise} - Modification du nom (ancien nom: {entreprise.nom})",
|
||||
)
|
||||
entreprise.nom = form.nom.data.strip()
|
||||
db.session.add(log)
|
||||
if entreprise.adresse != form.adresse.data.strip():
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=entreprise.id,
|
||||
text=f"{nom_entreprise} - Modification de l'adresse (ancienne adresse: {entreprise.adresse})",
|
||||
)
|
||||
entreprise.adresse = form.adresse.data.strip()
|
||||
db.session.add(log)
|
||||
if entreprise.codepostal != form.codepostal.data.strip():
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=entreprise.id,
|
||||
text=f"{nom_entreprise} - Modification du code postal (ancien code postal: {entreprise.codepostal})",
|
||||
)
|
||||
entreprise.codepostal = form.codepostal.data.strip()
|
||||
db.session.add(log)
|
||||
if entreprise.ville != form.ville.data.strip():
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=entreprise.id,
|
||||
text=f"{nom_entreprise} - Modification de la ville (ancienne ville: {entreprise.ville})",
|
||||
)
|
||||
entreprise.ville = form.ville.data.strip()
|
||||
db.session.add(log)
|
||||
if entreprise.pays != form.pays.data.strip() or not form.pays.data.strip():
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=entreprise.id,
|
||||
text=f"{nom_entreprise} - Modification du pays (ancien pays: {entreprise.pays})",
|
||||
)
|
||||
entreprise.pays = (
|
||||
form.pays.data.strip() if form.pays.data.strip() else "FRANCE"
|
||||
)
|
||||
db.session.add(log)
|
||||
entreprise.association = form.association.data
|
||||
db.session.commit()
|
||||
flash("L'entreprise a été modifié.")
|
||||
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
|
||||
@ -415,6 +458,7 @@ def edit_entreprise(id):
|
||||
form.codepostal.data = entreprise.codepostal
|
||||
form.ville.data = entreprise.ville
|
||||
form.pays.data = entreprise.pays
|
||||
form.association.data = entreprise.association
|
||||
return render_template(
|
||||
"entreprises/form_modification_entreprise.html",
|
||||
title="Modification entreprise",
|
||||
@ -428,21 +472,128 @@ def fiche_entreprise_desactiver(id):
|
||||
"""
|
||||
Permet de désactiver une entreprise
|
||||
"""
|
||||
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
|
||||
description=f"entreprise {id} inconnue"
|
||||
)
|
||||
entreprise = Entreprise.query.filter_by(
|
||||
id=id, visible=True, active=True
|
||||
).first_or_404(description=f"entreprise {id} inconnue")
|
||||
form = DesactivationConfirmationForm()
|
||||
if form.validate_on_submit():
|
||||
entreprise.notes_active = form.notes_active.data.strip()
|
||||
entreprise.active = False
|
||||
db.session.commit()
|
||||
flash("L'entreprise a été désactivé.")
|
||||
return redirect(url_for("entreprises.index"))
|
||||
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
|
||||
return render_template(
|
||||
"entreprises/confirmation_form.html",
|
||||
title="Désactiver entreprise",
|
||||
form=form,
|
||||
info_message="Cliquez sur le bouton Désactiver pour confirmer la désactivation",
|
||||
info_message="Cliquez sur le bouton Modifier 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",
|
||||
)
|
||||
|
||||
|
||||
@ -461,9 +612,10 @@ def validate_entreprise(id):
|
||||
if form.validate_on_submit():
|
||||
entreprise.visible = True
|
||||
nom_entreprise = f"<a href=/ScoDoc/entreprises/fiche_entreprise/{entreprise.id}>{entreprise.nom}</a>"
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom}) avec un correspondant",
|
||||
entreprise_id=entreprise.id,
|
||||
text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom})",
|
||||
)
|
||||
db.session.add(log)
|
||||
db.session.commit()
|
||||
@ -521,7 +673,9 @@ def add_offre(id):
|
||||
missions=form.missions.data.strip(),
|
||||
duree=form.duree.data.strip(),
|
||||
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.commit()
|
||||
@ -545,9 +699,11 @@ def add_offre(id):
|
||||
file = form.fichier.data
|
||||
filename = secure_filename(file.filename)
|
||||
file.save(os.path.join(path, filename))
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=entreprise.id,
|
||||
object="offre",
|
||||
object_id=offre.id,
|
||||
text="Création d'une offre",
|
||||
)
|
||||
db.session.add(log)
|
||||
@ -582,6 +738,9 @@ def edit_offre(id):
|
||||
offre.missions = form.missions.data.strip()
|
||||
offre.duree = form.duree.data.strip()
|
||||
offre.expiration_date = form.expiration_date.data
|
||||
if form.correspondant.data == "":
|
||||
offre.correspondant_id = sql.null()
|
||||
else:
|
||||
offre.correspondant_id = form.correspondant.data
|
||||
if offre_depts_list != form.depts.data:
|
||||
for dept in form.depts.data:
|
||||
@ -597,9 +756,11 @@ def edit_offre(id):
|
||||
offre_id=offre.id, dept_id=dept
|
||||
).first_or_404()
|
||||
db.session.delete(offre_dept)
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=offre.entreprise_id,
|
||||
entreprise_id=offre.entreprise_id,
|
||||
object="offre",
|
||||
object_id=offre.id,
|
||||
text="Modification d'une offre",
|
||||
)
|
||||
db.session.add(log)
|
||||
@ -642,9 +803,11 @@ def delete_offre(id):
|
||||
)
|
||||
if os.path.isdir(path):
|
||||
shutil.rmtree(path)
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=offre.entreprise_id,
|
||||
entreprise_id=offre.entreprise_id,
|
||||
object="offre",
|
||||
object_id=offre.id,
|
||||
text="Suppression d'une offre",
|
||||
)
|
||||
db.session.add(log)
|
||||
@ -700,7 +863,7 @@ def add_site(id):
|
||||
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
|
||||
description=f"entreprise {id} inconnue"
|
||||
)
|
||||
form = SiteCreationForm()
|
||||
form = SiteCreationForm(hidden_entreprise_id=id)
|
||||
if form.validate_on_submit():
|
||||
site = EntrepriseSite(
|
||||
entreprise_id=entreprise.id,
|
||||
@ -721,6 +884,41 @@ 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(
|
||||
"/fiche_entreprise/<int:id_entreprise>/add_correspondant/<int:id_site>",
|
||||
methods=["GET", "POST"],
|
||||
@ -752,13 +950,17 @@ def add_correspondant(id_entreprise, id_site):
|
||||
origine=correspondant_entry.origine.data.strip(),
|
||||
notes=correspondant_entry.notes.data.strip(),
|
||||
)
|
||||
log = EntrepriseLog(
|
||||
db.session.add(correspondant)
|
||||
db.session.commit()
|
||||
db.session.refresh(correspondant)
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=entreprise.id,
|
||||
entreprise_id=correspondant.entreprise_id,
|
||||
object="correspondant",
|
||||
object_id=correspondant.id,
|
||||
text="Création d'un correspondant",
|
||||
)
|
||||
db.session.add(log)
|
||||
db.session.add(correspondant)
|
||||
db.session.commit()
|
||||
flash("Le correspondant a été ajouté à la fiche entreprise.")
|
||||
return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id))
|
||||
@ -775,8 +977,11 @@ def edit_correspondant(id):
|
||||
"""
|
||||
Permet de modifier un correspondant
|
||||
"""
|
||||
correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404(
|
||||
description=f"correspondant {id} inconnu"
|
||||
correspondant = (
|
||||
db.session.query(EntrepriseCorrespondant)
|
||||
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
|
||||
.filter(EntrepriseCorrespondant.id == id, Entreprise.visible == True)
|
||||
.first_or_404(description=f"correspondant {id} inconnu")
|
||||
)
|
||||
form = CorrespondantModificationForm(
|
||||
hidden_entreprise_id=correspondant.entreprise_id,
|
||||
@ -792,9 +997,11 @@ def edit_correspondant(id):
|
||||
correspondant.service = form.service.data.strip()
|
||||
correspondant.origine = form.origine.data.strip()
|
||||
correspondant.notes = form.notes.data.strip()
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=correspondant.entreprise_id,
|
||||
entreprise_id=correspondant.entreprise_id,
|
||||
object="correspondant",
|
||||
object_id=correspondant.id,
|
||||
text="Modification d'un correspondant",
|
||||
)
|
||||
db.session.add(log)
|
||||
@ -826,15 +1033,20 @@ def delete_correspondant(id):
|
||||
"""
|
||||
Permet de supprimer un correspondant
|
||||
"""
|
||||
correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404(
|
||||
description=f"correspondant {id} inconnu"
|
||||
correspondant = (
|
||||
db.session.query(EntrepriseCorrespondant)
|
||||
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
|
||||
.filter(EntrepriseCorrespondant.id == id, Entreprise.visible == True)
|
||||
.first_or_404(description=f"correspondant {id} inconnu")
|
||||
)
|
||||
form = SuppressionConfirmationForm()
|
||||
if form.validate_on_submit():
|
||||
db.session.delete(correspondant)
|
||||
log = EntrepriseLog(
|
||||
log = EntrepriseHistorique(
|
||||
authenticated_user=current_user.user_name,
|
||||
object=correspondant.entreprise_id,
|
||||
entreprise_id=correspondant.entreprise_id,
|
||||
object="correspondant",
|
||||
object_id=correspondant.id,
|
||||
text="Suppression d'un correspondant",
|
||||
)
|
||||
db.session.add(log)
|
||||
@ -937,7 +1149,10 @@ def contacts(id):
|
||||
"""
|
||||
Permet d'afficher une page avec la liste des contacts d'une entreprise
|
||||
"""
|
||||
contacts = EntrepriseContact.query.filter_by(entreprise=id).all()
|
||||
entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404(
|
||||
description=f"entreprise {id} inconnue"
|
||||
)
|
||||
contacts = EntrepriseContact.query.filter_by(entreprise=entreprise.id).all()
|
||||
return render_template(
|
||||
"entreprises/contacts.html",
|
||||
title="Liste des contacts",
|
||||
@ -1125,7 +1340,7 @@ def json_etudiants():
|
||||
if request.args.get("term") is None:
|
||||
abort(400)
|
||||
term = request.args.get("term").strip()
|
||||
etudiants = Identite.query.filter(Identite.nom.ilike(f"%{term}%")).all()
|
||||
etudiants = Identite.query.filter(Identite.nom.ilike(f"%{term}%")).limit(30).all()
|
||||
list = []
|
||||
for etudiant in etudiants:
|
||||
content = {}
|
||||
@ -1134,10 +1349,14 @@ def json_etudiants():
|
||||
content = {
|
||||
"id": f"{etudiant.id}",
|
||||
"value": value,
|
||||
"info": f"{etudiant.inscription_courante().formsemestre.titre}",
|
||||
"info": f"Département {are.get_dept_acronym_by_id(etudiant.dept_id)} - {etudiant.inscription_courante().formsemestre.titre}",
|
||||
}
|
||||
else:
|
||||
content = {"id": f"{etudiant.id}", "value": value}
|
||||
content = {
|
||||
"id": f"{etudiant.id}",
|
||||
"value": value,
|
||||
"info": f"Département {are.get_dept_acronym_by_id(etudiant.dept_id)}",
|
||||
}
|
||||
list.append(content)
|
||||
return jsonify(results=list)
|
||||
|
||||
@ -1151,68 +1370,56 @@ def json_responsables():
|
||||
if request.args.get("term") is None:
|
||||
abort(400)
|
||||
term = request.args.get("term").strip()
|
||||
responsables = User.query.filter(
|
||||
responsables = (
|
||||
User.query.filter(
|
||||
User.nom.ilike(f"%{term}%"), User.nom.is_not(None), User.prenom.is_not(None)
|
||||
).all()
|
||||
)
|
||||
.limit(30)
|
||||
.all()
|
||||
)
|
||||
list = []
|
||||
|
||||
for responsable in responsables:
|
||||
content = {}
|
||||
value = f"{responsable.get_nomplogin()}"
|
||||
content = {"id": f"{responsable.id}", "value": value, "info": ""}
|
||||
content = {"id": f"{responsable.id}", "value": value}
|
||||
list.append(content)
|
||||
return jsonify(results=list)
|
||||
|
||||
|
||||
@bp.route("/export_entreprises")
|
||||
@bp.route("/export_donnees")
|
||||
@permission_required(Permission.RelationsEntreprisesExport)
|
||||
def export_entreprises():
|
||||
def export_donnees():
|
||||
"""
|
||||
Permet d'exporter la liste des entreprises sous format excel (.xlsx)
|
||||
"""
|
||||
entreprises = Entreprise.query.filter_by(visible=True).all()
|
||||
if entreprises:
|
||||
keys = ["siret", "nom_entreprise", "adresse", "ville", "code_postal", "pays"]
|
||||
titles = keys[:]
|
||||
L = [
|
||||
[entreprise.to_dict().get(k, "") for k in keys]
|
||||
for entreprise in entreprises
|
||||
]
|
||||
title = "Entreprises"
|
||||
xlsx = sco_excel.excel_simple_table(titles=titles, lines=L, sheet_name=title)
|
||||
filename = title
|
||||
entreprise = Entreprise.query.filter_by(visible=True).first()
|
||||
if entreprise:
|
||||
wb = are.get_excel_book_are(export=True)
|
||||
xlsx = wb.generate()
|
||||
filename = "ExportApplicationRelationsEntreprises"
|
||||
return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
|
||||
else:
|
||||
flash("Aucune entreprise dans la base.")
|
||||
return redirect(url_for("entreprises.index"))
|
||||
|
||||
|
||||
@bp.route("/import_entreprises/get_import_entreprises_file_sample")
|
||||
@bp.route("/import_donnees/get_file_sample")
|
||||
@permission_required(Permission.RelationsEntreprisesExport)
|
||||
def get_import_entreprises_file_sample():
|
||||
def get_import_donnees_file_sample():
|
||||
"""
|
||||
Permet de récupérer un fichier exemple vide pour pouvoir importer des entreprises
|
||||
"""
|
||||
keys = [
|
||||
"siret",
|
||||
"nom_entreprise",
|
||||
"adresse",
|
||||
"ville",
|
||||
"code_postal",
|
||||
"pays",
|
||||
]
|
||||
titles = keys[:]
|
||||
title = "ImportEntreprises"
|
||||
xlsx = sco_excel.excel_simple_table(titles=titles, sheet_name="Entreprises")
|
||||
filename = title
|
||||
wb = are.get_excel_book_are()
|
||||
xlsx = wb.generate()
|
||||
filename = "ImportApplicationRelationsEntreprises"
|
||||
return scu.send_file(xlsx, filename, scu.XLSX_SUFFIX, scu.XLSX_MIMETYPE)
|
||||
|
||||
|
||||
@bp.route("/import_entreprises", methods=["GET", "POST"])
|
||||
@bp.route("/import_donnees", methods=["GET", "POST"])
|
||||
@permission_required(Permission.RelationsEntreprisesExport)
|
||||
def import_entreprises():
|
||||
def import_donnees():
|
||||
"""
|
||||
Permet d'importer des entreprises a l'aide d'un fichier excel (.xlsx)
|
||||
Permet d'importer des entreprises à partir d'un fichier excel (.xlsx)
|
||||
"""
|
||||
form = ImportForm()
|
||||
if form.validate_on_submit():
|
||||
@ -1221,237 +1428,58 @@ def import_entreprises():
|
||||
Config.SCODOC_VAR_DIR, "tmp", secure_filename(file.filename)
|
||||
)
|
||||
file.save(file_path)
|
||||
data = sco_excel.excel_file_to_list(file_path)
|
||||
diag, lm = sco_excel.excel_workbook_to_list(file_path)
|
||||
os.remove(file_path)
|
||||
entreprises_import = []
|
||||
siret_list = []
|
||||
ligne = 0
|
||||
titles = ["siret", "nom_entreprise", "adresse", "ville", "code_postal", "pays"]
|
||||
if data[1][0] != titles:
|
||||
if lm is None or len(lm) < 2:
|
||||
flash("Veuillez utilisez la feuille excel à remplir")
|
||||
return render_template(
|
||||
"entreprises/import_entreprises.html",
|
||||
title="Importation entreprises",
|
||||
form=form,
|
||||
)
|
||||
for entreprise_data in data[1][1:]:
|
||||
ligne += 1
|
||||
return redirect(url_for("entreprises.import_donnees"))
|
||||
entreprises_import = are.check_entreprises_import(lm[0])
|
||||
sites_import, correspondants_import = are.check_sites_import(lm[1])
|
||||
if (
|
||||
are.verif_entreprise_data(entreprise_data)
|
||||
and entreprise_data[0].replace(" ", "") not in siret_list
|
||||
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)
|
||||
):
|
||||
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:
|
||||
flash(f"Erreur lors de l'importation (ligne {ligne})")
|
||||
return render_template(
|
||||
"entreprises/import_entreprises.html",
|
||||
title="Importation entreprises",
|
||||
form=form,
|
||||
)
|
||||
|
||||
if len(entreprises_import) > 0:
|
||||
return redirect(url_for("entreprises.import_donnees"))
|
||||
for entreprise in entreprises_import:
|
||||
db.session.add(entreprise)
|
||||
log = EntrepriseLog(
|
||||
authenticated_user=current_user.user_name,
|
||||
text=f"Importation de {len(entreprises_import)} entreprise(s)",
|
||||
)
|
||||
db.session.add(log)
|
||||
db.session.commit()
|
||||
flash(f"Importation réussie de {len(entreprises_import)} entreprise(s)")
|
||||
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 site in sites_import:
|
||||
db.session.add(site)
|
||||
correspondants = []
|
||||
for site, correspondant in correspondants_import:
|
||||
if site is None:
|
||||
db.session.add(correspondant)
|
||||
else:
|
||||
db.session.add(site)
|
||||
db.session.commit()
|
||||
db.session.refresh(site)
|
||||
correspondant.site_id = site.id
|
||||
db.session.add(correspondant)
|
||||
correspondants.append(correspondant)
|
||||
db.session.commit()
|
||||
flash(f"Importation réussie")
|
||||
return render_template(
|
||||
"entreprises/import_entreprises.html",
|
||||
title="Importation entreprises",
|
||||
"entreprises/import_donnees.html",
|
||||
title="Importation données",
|
||||
form=form,
|
||||
entreprises_import=entreprises_import,
|
||||
)
|
||||
else:
|
||||
flash('Feuille "Entreprises" vide')
|
||||
|
||||
return render_template(
|
||||
"entreprises/import_entreprises.html",
|
||||
title="Importation entreprises",
|
||||
form=form,
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/export_correspondants")
|
||||
@permission_required(Permission.RelationsEntreprisesExport)
|
||||
def export_correspondants():
|
||||
"""
|
||||
Permet d'exporter la liste des correspondants sous format excel (.xlsx)
|
||||
"""
|
||||
correspondants = (
|
||||
db.session.query(EntrepriseCorrespondant)
|
||||
.join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id)
|
||||
.filter_by(visible=True)
|
||||
.all()
|
||||
)
|
||||
if correspondants:
|
||||
keys = [
|
||||
"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)"
|
||||
sites_import=sites_import,
|
||||
correspondants_import=correspondants,
|
||||
)
|
||||
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,
|
||||
"entreprises/import_donnees.html", title="Importation données", form=form
|
||||
)
|
||||
|
||||
|
||||
|
@ -40,10 +40,9 @@ from openpyxl.comments import Comment
|
||||
from openpyxl import Workbook, load_workbook
|
||||
from openpyxl.cell import WriteOnlyCell
|
||||
from openpyxl.styles import Font, Border, Side, Alignment, PatternFill
|
||||
from openpyxl.worksheet.worksheet import Worksheet
|
||||
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc import notesdb
|
||||
from app.scodoc import sco_preferences
|
||||
from app import log
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
|
||||
@ -593,60 +592,87 @@ def excel_feuille_saisie(e, titreannee, description, lines):
|
||||
def excel_bytes_to_list(bytes_content):
|
||||
try:
|
||||
filelike = io.BytesIO(bytes_content)
|
||||
return _excel_to_list(filelike)
|
||||
except:
|
||||
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
|
||||
return _excel_to_list(filelike)
|
||||
|
||||
|
||||
def excel_file_to_list(filename):
|
||||
try:
|
||||
return _excel_to_list(filename)
|
||||
except:
|
||||
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 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):
|
||||
"""returns list of list
|
||||
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 !"
|
||||
)
|
||||
"""returns list of list"""
|
||||
workbook = _open_workbook(filelike)
|
||||
diag = [] # liste de chaines pour former message d'erreur
|
||||
# n'utilise que la première feuille
|
||||
if len(wb.get_sheet_names()) < 1:
|
||||
if len(workbook.get_sheet_names()) < 1:
|
||||
diag.append("Aucune feuille trouvée dans le classeur !")
|
||||
return diag, None
|
||||
if len(wb.get_sheet_names()) > 1:
|
||||
# n'utilise que la première feuille:
|
||||
if len(workbook.get_sheet_names()) > 1:
|
||||
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
|
||||
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 = {}
|
||||
for row in ws.iter_rows():
|
||||
for row in sheet.iter_rows():
|
||||
for cell in row:
|
||||
if cell.value is not None:
|
||||
values[(cell.row - 1, cell.column - 1)] = str(cell.value)
|
||||
if not values:
|
||||
diag.append(
|
||||
"Aucune valeur trouvée dans la feuille %s !"
|
||||
% sheet_name.decode(scu.SCO_ENCODING)
|
||||
)
|
||||
diag.append(f"Aucune valeur trouvée dans la feuille {sheet_name} !")
|
||||
return diag, None
|
||||
indexes = list(values.keys())
|
||||
# search numbers of rows and cols
|
||||
@ -654,23 +680,38 @@ def _excel_to_list(filelike):
|
||||
cols = [x[1] for x in indexes]
|
||||
nbcols = max(cols) + 1
|
||||
nbrows = max(rows) + 1
|
||||
m = []
|
||||
matrix = []
|
||||
for _ in range(nbrows):
|
||||
m.append([""] * nbcols)
|
||||
matrix.append([""] * nbcols)
|
||||
|
||||
for row_idx, col_idx in indexes:
|
||||
v = values[(row_idx, col_idx)]
|
||||
# if isinstance(v, six.text_type):
|
||||
# v = v.encode(scu.SCO_ENCODING, "backslashreplace")
|
||||
# elif convert_to_string:
|
||||
# v = convert_to_string(v)
|
||||
m[row_idx][col_idx] = v
|
||||
diag.append(
|
||||
'Feuille "%s", %d lignes' % (sheet_name.decode(scu.SCO_ENCODING), len(m))
|
||||
)
|
||||
# diag.append(str(M))
|
||||
#
|
||||
return diag, m
|
||||
matrix[row_idx][col_idx] = v
|
||||
diag.append(f'Feuille "{sheet_name}", {len(matrix)} lignes')
|
||||
|
||||
return diag, matrix
|
||||
|
||||
|
||||
def _excel_workbook_to_list(filelike):
|
||||
"""Lit un classeur (workbook): chaque feuille est lue
|
||||
et est convertie en une liste de listes.
|
||||
Returns:
|
||||
- diag : a list of strings (error messages aimed at helping the user)
|
||||
- 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(
|
||||
|
@ -1,28 +1,37 @@
|
||||
.nav-entreprise>ul {
|
||||
padding-left: 0;
|
||||
.nav-entreprise {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.nav-entreprise ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-entreprise li{
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
border: 2px black solid;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.nav-entreprise li:hover{
|
||||
background-color: rgb(212, 212, 212);
|
||||
}
|
||||
|
||||
.nav-entreprise>ul>li>a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.nav-entreprise>ul>li>a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
color: #a94442;
|
||||
}
|
||||
|
||||
.nav-entreprise>ul>li>a:hover {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.boutons .btn {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
@ -59,14 +68,33 @@
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
||||
.entreprise, .correspondant, .offre, .site{
|
||||
border: solid 2px;
|
||||
.entreprise, .correspondant, .offre, .site, .info-active {
|
||||
border: solid 2px black;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin-bottom: 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 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -102,3 +130,46 @@
|
||||
border-radius: 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;
|
||||
}
|
@ -16,7 +16,11 @@
|
||||
</p>
|
||||
<form method="POST" action="" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
{{ form.correspondants.label }}
|
||||
{% for subfield in form.correspondants %}
|
||||
{% if subfield.errors %}
|
||||
<p class="title-form-error">Formulaire {{ subfield.label.text }}</p>
|
||||
{% endif %}
|
||||
{% for subsubfield in subfield %}
|
||||
{% if subsubfield.errors %}
|
||||
{% for error in subsubfield.errors %}
|
||||
@ -56,7 +60,22 @@
|
||||
}
|
||||
let newFieldName = `correspondants-${Math.max(...correspondantInputIds) + 1}`;
|
||||
allCorrepondantsFieldWrapper.insertAdjacentHTML('beforeend',`
|
||||
<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>
|
||||
<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>
|
||||
`);
|
||||
});
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
{% block app_content %}
|
||||
<h1>{{ title }}</h1>
|
||||
<br>
|
||||
<div style="color:red;">{{ info_message }}</div>
|
||||
<div>{{ info_message }}</div>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
|
@ -9,7 +9,21 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block app_content %}
|
||||
<div class="container" style="margin-bottom: 10px;">
|
||||
<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">Contacts</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 10px;">
|
||||
<h1>Liste des contacts</h1>
|
||||
{% 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>
|
||||
|
@ -22,15 +22,6 @@
|
||||
</div>
|
||||
{% 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;">
|
||||
<h1>Liste des correspondants</h1>
|
||||
<table id="table-correspondants">
|
||||
@ -54,7 +45,7 @@
|
||||
<td>{{ correspondant[0].mail }}</td>
|
||||
<td>{{ correspondant[0].poste}}</td>
|
||||
<td>{{ correspondant[0].service}}</td>
|
||||
<td><a href="{{ url_for('entreprises.fiche_entreprise', id=correspondant[1].id) }}">{{ correspondant[1].nom }}</a></td>
|
||||
<td><a href="{{ url_for('entreprises.fiche_entreprise', id=correspondant[1].entreprise_id) }}">{{ correspondant[1].nom }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -27,15 +27,22 @@
|
||||
<a class="btn btn-default" href="{{ url_for('entreprises.add_entreprise') }}">Ajouter une entreprise</a>
|
||||
{% endif %}
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %}
|
||||
<a class="btn btn-default" href="{{ url_for('entreprises.import_entreprises') }}">Importer des entreprises</a>
|
||||
<a class="btn btn-default" href="{{ url_for('entreprises.import_donnees') }}">Importer des données</a>
|
||||
{% endif %}
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and entreprises %}
|
||||
<a class="btn btn-default" href="{{ url_for('entreprises.export_entreprises') }}">Exporter la liste des entreprises</a>
|
||||
<a class="btn btn-default" href="{{ url_for('entreprises.export_donnees') }}">Exporter des données</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="container" style="margin-bottom: 10px;">
|
||||
<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">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -53,7 +60,7 @@
|
||||
<tbody>
|
||||
{% for entreprise in entreprises %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}">{{ entreprise.siret }}</a></td>
|
||||
<td><a href="{{ url_for('entreprises.fiche_entreprise', id=entreprise.id) }}" {% if not entreprise.active %} style="color:red" {% endif %}>{{ entreprise.siret }}</a></td>
|
||||
<td>{{ entreprise.nom }}</td>
|
||||
<td>{{ entreprise.adresse }}</td>
|
||||
<td>{{ entreprise.codepostal }}</td>
|
||||
@ -67,7 +74,11 @@
|
||||
</a>
|
||||
<ul class="dropdown-menu pull-left">
|
||||
<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>
|
||||
{% else %}
|
||||
<li><a href="{{ url_for('entreprises.fiche_entreprise_activer', id=entreprise.id)}}" style="color:lightgreen">Activer</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -18,14 +18,10 @@
|
||||
</p>
|
||||
<form method="POST" action="" novalidate>
|
||||
{{ form.hidden_tag() }}
|
||||
{{ form.responsables.label }}<br>
|
||||
{% for subfield in form.responsables %}
|
||||
{% if subfield.errors %}
|
||||
{% for error in subfield.errors %}
|
||||
{{ form.responsables.label }}
|
||||
{% for error in form.responsables.errors %}
|
||||
<p class="help-block form-error">{{ error }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ form.responsables }}
|
||||
<div style="margin-bottom: 10px;">
|
||||
<button class="btn btn-default" id="add-responsable-field">Ajouter un responsable</button>
|
||||
@ -71,7 +67,11 @@
|
||||
}
|
||||
let newFieldName = `responsables-${Math.max(...responsableInputIds) + 1}`;
|
||||
allResponsablesFieldWrapper.insertAdjacentHTML('beforeend',`
|
||||
<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>
|
||||
<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);
|
||||
});
|
||||
|
@ -9,6 +9,17 @@
|
||||
{% 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">Fiche entreprise</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{% if logs %}
|
||||
<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>
|
||||
@ -26,6 +37,15 @@
|
||||
<div class="container fiche-entreprise">
|
||||
<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>
|
||||
SIRET : {{ entreprise.siret }}<br>
|
||||
@ -33,14 +53,41 @@
|
||||
Adresse : {{ entreprise.adresse }}<br>
|
||||
Code postal : {{ entreprise.codepostal }}<br>
|
||||
Ville : {{ entreprise.ville }}<br>
|
||||
Pays : {{ entreprise.pays }}
|
||||
Pays : {{ entreprise.pays }}<br>
|
||||
{% if entreprise.association %}
|
||||
Association
|
||||
{% endif %}
|
||||
</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>
|
||||
{% 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>
|
||||
{% if entreprise.active %}
|
||||
<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_offre', id=entreprise.id) }}">Ajouter offre</a>
|
||||
{% endif %}
|
||||
@ -61,7 +108,10 @@
|
||||
Ville : {{ site.ville }}<br>
|
||||
Pays : {{ site.pays }}
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||
<br><a class="btn btn-primary" href="{{ url_for('entreprises.add_correspondant', id_entreprise=entreprise.id, id_site=site.id) }}">Ajouter correspondant</a>
|
||||
<div>
|
||||
<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 %}
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
||||
{% for correspondant in site.correspondants %}
|
||||
@ -111,7 +161,7 @@
|
||||
<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].type_offre }}</td>
|
||||
<td>{{ data[1].nom|format_nom }} {{ data[1].prenom|format_prenom }}</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>{% if data[0].formation_text %}{{ data[0].formation_text }}{% endif %}</td>
|
||||
<td>{{ data[0].notes }}</td>
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||
|
@ -12,16 +12,29 @@
|
||||
Adresse : {{ entreprise.adresse }}<br>
|
||||
Code postal : {{ entreprise.codepostal }}<br>
|
||||
Ville : {{ entreprise.ville }}<br>
|
||||
Pays : {{ entreprise.pays }}
|
||||
Pays : {{ entreprise.pays }}<br>
|
||||
{% if entreprise.association %}
|
||||
Association
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if correspondants %}
|
||||
<div class="sites-et-offres">
|
||||
{% if sites %}
|
||||
<div>
|
||||
{% for correspondant in correspondants %}
|
||||
<div>
|
||||
<h3>Correspondant</h3>
|
||||
<h3>Sites</h3>
|
||||
{% for site in sites %}
|
||||
<div class="site">
|
||||
Nom : {{ site.nom }}<br>
|
||||
Adresse : {{ site.adresse }}<br>
|
||||
Code postal : {{ site.codepostal }}<br>
|
||||
Ville : {{ site.ville }}<br>
|
||||
Pays : {{ site.pays }}
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
||||
{% for correspondant in site.correspondants %}
|
||||
<div class="correspondant">
|
||||
<div>
|
||||
Civilité : {{ correspondant.civilite|get_civilité }}<br>
|
||||
Nom : {{ correspondant.nom }}<br>
|
||||
Prénom : {{ correspondant.prenom }}<br>
|
||||
{% if correspondant.telephone %}
|
||||
@ -36,11 +49,21 @@
|
||||
{% 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 %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="btn btn-success" href="{{ url_for('entreprises.validate_entreprise', id=entreprise.id) }}">Valider</a>
|
||||
|
@ -1,72 +0,0 @@
|
||||
{# -*- 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 %}
|
149
app/templates/entreprises/import_donnees.html
Normal file
149
app/templates/entreprises/import_donnees.html
Normal file
@ -0,0 +1,149 @@
|
||||
{# -*- 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 %}
|
@ -1,52 +0,0 @@
|
||||
{# -*- 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 %}
|
@ -2,6 +2,17 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% 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">
|
||||
<h3>Dernières opérations</h3>
|
||||
{% if logs.items %}
|
||||
|
@ -2,6 +2,20 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% 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">
|
||||
<h3>Dernières opérations - {{ entreprise.nom }}</h3>
|
||||
{% if logs.items %}
|
||||
|
@ -1,5 +1,6 @@
|
||||
{# -*- mode: jinja-html -*- #}
|
||||
<nav class="nav-entreprise">
|
||||
<div class="container">
|
||||
<nav class="nav-entreprise">
|
||||
<ul>
|
||||
<li><a href="{{ url_for('entreprises.index') }}">Entreprises</a></li>
|
||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
||||
@ -11,4 +12,5 @@
|
||||
<li><a href="{{ url_for('entreprises.preferences') }}">Préférences</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</nav>
|
||||
</div>
|
@ -2,6 +2,20 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% 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">
|
||||
<h1>Offres expirées - {{ entreprise.nom }}</h1>
|
||||
{% if offres_expirees %}
|
||||
|
@ -5,6 +5,7 @@
|
||||
{% block app_content %}
|
||||
{% include 'entreprises/nav.html' %}
|
||||
|
||||
<div class="container">
|
||||
<h1>Préférences module gestion entreprises</h1>
|
||||
<br>
|
||||
<div class="row">
|
||||
@ -12,4 +13,5 @@
|
||||
{{ wtf.quick_form(form, novalidate=True) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,76 @@
|
||||
"""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 ###
|
Loading…
Reference in New Issue
Block a user