From 5f5c43ec089a23bdf6e7385331cd651e2a1b046b Mon Sep 17 00:00:00 2001 From: Arthur ZHU Date: Fri, 4 Mar 2022 17:10:07 +0100 Subject: [PATCH 01/17] associer un contact a une offre --- app/entreprises/app_relations_entreprises.py | 3 +- app/entreprises/forms.py | 34 +++++++++++++++++++ app/entreprises/models.py | 12 +++++++ app/entreprises/routes.py | 12 +++++-- app/templates/entreprises/_offre.html | 13 +++++++ app/templates/entreprises/offres_recues.html | 10 ++++++ ...74b7a_tables_module_gestion_relations_.py} | 14 +++++--- 7 files changed, 89 insertions(+), 9 deletions(-) rename migrations/versions/{af05f03b81be_tables_module_gestion_relations_.py => 40ece1f74b7a_tables_module_gestion_relations_.py} (97%) diff --git a/app/entreprises/app_relations_entreprises.py b/app/entreprises/app_relations_entreprises.py index 68ff9986..6b2a2e56 100644 --- a/app/entreprises/app_relations_entreprises.py +++ b/app/entreprises/app_relations_entreprises.py @@ -85,6 +85,7 @@ def get_offre_files_and_depts(offre: EntrepriseOffre, depts: list): Retourne l'offre, les fichiers attachés a l'offre et les département liés """ offre_depts = EntrepriseOffreDepartement.query.filter_by(offre_id=offre.id).all() + contact = EntrepriseContact.query.filter_by(id=offre.contact_id).first() if not offre_depts or check_offre_depts(depts, offre_depts): files = [] path = os.path.join( @@ -100,7 +101,7 @@ def get_offre_files_and_depts(offre: EntrepriseOffre, depts: list): for _file in glob.glob(f"{dir}/*"): file = [os.path.basename(dir), os.path.basename(_file)] files.append(file) - return [offre, files, offre_depts] + return [offre, files, offre_depts, contact] return None diff --git a/app/entreprises/forms.py b/app/entreprises/forms.py index 0540c080..19719bcc 100644 --- a/app/entreprises/forms.py +++ b/app/entreprises/forms.py @@ -144,6 +144,7 @@ class MultiCheckboxField(SelectMultipleField): class OffreCreationForm(FlaskForm): + hidden_entreprise_id = HiddenField() intitule = _build_string_field("Intitulé (*)") description = TextAreaField( "Description (*)", validators=[DataRequired(message=CHAMP_REQUIS)] @@ -159,17 +160,26 @@ class OffreCreationForm(FlaskForm): duree = _build_string_field("Durée (*)") depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) expiration_date = DateField("Date expiration", validators=[Optional()]) + contact = SelectField("Contact à contacté (*)", validators=[Optional()]) submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.contact.choices = [ + (contact.id, f"{contact.nom} {contact.prenom}") + for contact in EntrepriseContact.query.filter_by( + entreprise_id=self.hidden_entreprise_id.data + ) + ] + self.depts.choices = [ (dept.id, dept.acronym) for dept in Departement.query.all() ] class OffreModificationForm(FlaskForm): + hidden_entreprise_id = HiddenField() intitule = _build_string_field("Intitulé (*)") description = TextAreaField( "Description (*)", validators=[DataRequired(message=CHAMP_REQUIS)] @@ -185,11 +195,19 @@ class OffreModificationForm(FlaskForm): duree = _build_string_field("Durée (*)") depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) expiration_date = DateField("Date expiration", validators=[Optional()]) + contact = SelectField("Contact à contacté (*)", validators=[Optional()]) submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.contact.choices = [ + (contact.id, f"{contact.nom} {contact.prenom}") + for contact in EntrepriseContact.query.filter_by( + entreprise_id=self.hidden_entreprise_id.data + ) + ] + self.depts.choices = [ (dept.id, dept.acronym) for dept in Departement.query.all() ] @@ -206,8 +224,16 @@ class ContactCreationForm(FlaskForm): ) poste = _build_string_field("Poste", required=False) service = _build_string_field("Service", required=False) + # depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE) + # def __init__(self, *args, **kwargs): + # super().__init__(*args, **kwargs) + + # self.depts.choices = [ + # (dept.id, dept.acronym) for dept in Departement.query.all() + # ] + def validate(self): validate = True if not FlaskForm.validate(self): @@ -245,8 +271,16 @@ class ContactModificationForm(FlaskForm): ) poste = _build_string_field("Poste", required=False) service = _build_string_field("Service", required=False) + # depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE) + # def __init__(self, *args, **kwargs): + # super().__init__(*args, **kwargs) + + # self.depts.choices = [ + # (dept.id, dept.acronym) for dept in Departement.query.all() + # ] + def validate(self): validate = True if not FlaskForm.validate(self): diff --git a/app/entreprises/models.py b/app/entreprises/models.py index dd0b4ba4..b4c1e7ca 100644 --- a/app/entreprises/models.py +++ b/app/entreprises/models.py @@ -75,6 +75,9 @@ class EntrepriseOffre(db.Model): duree = db.Column(db.Text) expiration_date = db.Column(db.Date) expired = db.Column(db.Boolean, default=False) + contact_id = db.Column( + db.Integer, db.ForeignKey("are_contacts.id", ondelete="cascade") + ) def to_dict(self): return { @@ -136,6 +139,15 @@ class EntrepriseOffreDepartement(db.Model): dept_id = db.Column(db.Integer, db.ForeignKey("departement.id", ondelete="cascade")) +# class EntrepriseContactDepartement(db.Model): +# __tablename__ = "are_contact_departement" +# id = db.Column(db.Integer, primary_key=True) +# contact_id = db.Column( +# db.Integer, db.ForeignKey("are_contacts.id", ondelete="cascade") +# ) +# dept_id = db.Column(db.Integer, db.ForeignKey("departement.id", ondelete="cascade")) + + class EntreprisePreferences(db.Model): __tablename__ = "are_preferences" id = db.Column(db.Integer, primary_key=True) diff --git a/app/entreprises/routes.py b/app/entreprises/routes.py index d1633e71..281ad047 100644 --- a/app/entreprises/routes.py +++ b/app/entreprises/routes.py @@ -221,6 +221,7 @@ def offres_recues(): ) offres_recues_with_files = [] for offre in offres_recues: + contact = EntrepriseContact.query.filter_by(id=offre[1].contact_id).first() files = [] path = os.path.join( Config.SCODOC_VAR_DIR, @@ -235,7 +236,7 @@ def offres_recues(): for file in glob.glob(f"{dir}/*"): file = [os.path.basename(dir), os.path.basename(file)] files.append(file) - offres_recues_with_files.append([offre[0], offre[1], files]) + offres_recues_with_files.append([offre[0], offre[1], files, contact]) return render_template( "entreprises/offres_recues.html", title="Offres reçues", @@ -491,7 +492,7 @@ def add_offre(id): entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) - form = OffreCreationForm() + form = OffreCreationForm(hidden_entreprise_id=id) if form.validate_on_submit(): offre = EntrepriseOffre( entreprise_id=entreprise.id, @@ -501,6 +502,7 @@ def add_offre(id): missions=form.missions.data.strip(), duree=form.duree.data.strip(), expiration_date=form.expiration_date.data, + contact_id=form.contact.data, ) db.session.add(offre) db.session.commit() @@ -537,15 +539,19 @@ def edit_offre(id): description=f"offre {id} inconnue" ) offre_depts = EntrepriseOffreDepartement.query.filter_by(offre_id=offre.id).all() - form = OffreModificationForm() + form = OffreModificationForm( + hidden_entreprise_id=offre.entreprise_id, contact=offre.contact_id + ) offre_depts_list = [(offre_dept.dept_id) for offre_dept in offre_depts] if form.validate_on_submit(): + print(form.contact.data) offre.intitule = form.intitule.data.strip() offre.description = form.description.data.strip() offre.type_offre = form.type_offre.data.strip() offre.missions = form.missions.data.strip() offre.duree = form.duree.data.strip() offre.expiration_date = form.expiration_date.data + offre.contact_id = form.contact.data if offre_depts_list != form.depts.data: for dept in form.depts.data: if dept not in offre_depts_list: diff --git a/app/templates/entreprises/_offre.html b/app/templates/entreprises/_offre.html index cff6f03a..11391da3 100644 --- a/app/templates/entreprises/_offre.html +++ b/app/templates/entreprises/_offre.html @@ -9,6 +9,16 @@ {% if offre[2] %} Département(s) : {% for offre_dept in offre[2] %}
{{ offre_dept.dept_id|get_dept_acronym }}
{% endfor %}
{% endif %} + + {% if offre[0].contact_id %} + Contacté {{ offre[3].nom }} {{ offre[3].prenom }} + {% if offre[3].mail and offre[3].telephone %} + ({{ offre[3].mail }} - {{ offre[3].telephone }})
+ {% else %} + ({{ offre[3].mail }}{{offre[3].telephone}})
+ {% endif %} + {% endif %} + {% for fichier in offre[1] %} {{ fichier[1] }} {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} @@ -16,6 +26,7 @@ {% endif %}
{% endfor %} + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} Ajoutez un fichier {% endif %} @@ -26,9 +37,11 @@ Modifier l'offre Supprimer l'offre {% endif %} + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesSend, None) %} Envoyer l'offre {% endif %} + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} {% if not offre[0].expired %} Rendre expirée diff --git a/app/templates/entreprises/offres_recues.html b/app/templates/entreprises/offres_recues.html index a8814739..e070ed50 100644 --- a/app/templates/entreprises/offres_recues.html +++ b/app/templates/entreprises/offres_recues.html @@ -16,6 +16,16 @@ Type de l'offre : {{ offre[1].type_offre }}
Missions : {{ offre[1].missions }}
Durée : {{ offre[1].duree }}
+ + {% if offre[1].contact_id %} + Contacté {{ offre[3].nom }} {{ offre[3].prenom }} + {% if offre[3].mail and offre[3].telephone %} + ({{ offre[3].mail }} - {{ offre[3].telephone }})
+ {% else %} + ({{ offre[3].mail }}{{offre[3].telephone}})
+ {% endif %} + {% endif %} + lien vers l'entreprise
{% for fichier in offre[2] %} diff --git a/migrations/versions/af05f03b81be_tables_module_gestion_relations_.py b/migrations/versions/40ece1f74b7a_tables_module_gestion_relations_.py similarity index 97% rename from migrations/versions/af05f03b81be_tables_module_gestion_relations_.py rename to migrations/versions/40ece1f74b7a_tables_module_gestion_relations_.py index 7f23ca9f..3afa6a87 100644 --- a/migrations/versions/af05f03b81be_tables_module_gestion_relations_.py +++ b/migrations/versions/40ece1f74b7a_tables_module_gestion_relations_.py @@ -1,8 +1,8 @@ """tables module gestion relations entreprises -Revision ID: af05f03b81be +Revision ID: 40ece1f74b7a Revises: b9aadc10227f -Create Date: 2022-03-01 17:12:32.927643 +Create Date: 2022-03-04 16:06:28.163870 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. -revision = "af05f03b81be" +revision = "40ece1f74b7a" down_revision = "b9aadc10227f" branch_labels = None depends_on = None @@ -98,6 +98,10 @@ def upgrade(): sa.Column("duree", sa.Text(), nullable=True), sa.Column("expiration_date", sa.Date(), nullable=True), sa.Column("expired", sa.Boolean(), nullable=True), + sa.Column("contact_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint( + ["contact_id"], ["are_contacts.id"], ondelete="cascade" + ), sa.ForeignKeyConstraint( ["entreprise_id"], ["are_entreprises.id"], ondelete="cascade" ), @@ -146,9 +150,9 @@ def upgrade(): sa.ForeignKeyConstraint(["offre_id"], ["are_offres.id"], ondelete="cascade"), sa.PrimaryKeyConstraint("id"), ) + op.drop_index("ix_entreprises_dept_id", table_name="entreprises") op.drop_table("entreprise_contact") op.drop_table("entreprise_correspondant") - op.drop_index("ix_entreprises_dept_id", table_name="entreprises") op.drop_table("entreprises") # ### end Alembic commands ### @@ -190,7 +194,6 @@ def downgrade(): sa.PrimaryKeyConstraint("id", name="entreprises_pkey"), postgresql_ignore_search_path=False, ) - op.create_index("ix_entreprises_dept_id", "entreprises", ["dept_id"], unique=False) op.create_table( "entreprise_correspondant", sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False), @@ -242,6 +245,7 @@ def downgrade(): ), sa.PrimaryKeyConstraint("id", name="entreprise_contact_pkey"), ) + op.create_index("ix_entreprises_dept_id", "entreprises", ["dept_id"], unique=False) op.drop_table("are_offre_departement") op.drop_table("are_envoi_offre_etudiant") op.drop_table("are_envoi_offre") From dc0212b725a3d4e2e91a76b5f08162d047c083b2 Mon Sep 17 00:00:00 2001 From: Arthur ZHU Date: Mon, 28 Mar 2022 23:44:57 +0200 Subject: [PATCH 02/17] refactoring, datatable stage/apprentissage fiche entreprise --- app/entreprises/app_relations_entreprises.py | 68 ++-- app/entreprises/forms.py | 112 ++++-- app/entreprises/models.py | 24 +- app/entreprises/routes.py | 358 +++++++++++------- app/static/css/entreprises.css | 8 +- app/templates/entreprises/_contact.html | 26 -- app/templates/entreprises/_correspondant.html | 26 ++ app/templates/entreprises/_offre.html | 2 +- .../entreprises/ajout_entreprise.html | 2 +- ...ue.html => ajout_stage_apprentissage.html} | 2 +- .../{contacts.html => correspondants.html} | 28 +- .../entreprises/fiche_entreprise.html | 127 +++++-- .../fiche_entreprise_validation.html | 28 +- .../entreprises/import_contacts.html | 62 --- .../entreprises/import_correspondants.html | 62 +++ app/templates/entreprises/nav.html | 2 +- app/templates/entreprises/offres_recues.html | 2 +- ...645e5_tables_module_gestion_relations_.py} | 64 ++-- 18 files changed, 603 insertions(+), 400 deletions(-) delete mode 100644 app/templates/entreprises/_contact.html create mode 100644 app/templates/entreprises/_correspondant.html rename app/templates/entreprises/{ajout_historique.html => ajout_stage_apprentissage.html} (97%) rename app/templates/entreprises/{contacts.html => correspondants.html} (80%) delete mode 100644 app/templates/entreprises/import_contacts.html create mode 100644 app/templates/entreprises/import_correspondants.html rename migrations/versions/{40ece1f74b7a_tables_module_gestion_relations_.py => 72ae180645e5_tables_module_gestion_relations_.py} (96%) diff --git a/app/entreprises/app_relations_entreprises.py b/app/entreprises/app_relations_entreprises.py index 6b2a2e56..d11b6aca 100644 --- a/app/entreprises/app_relations_entreprises.py +++ b/app/entreprises/app_relations_entreprises.py @@ -34,7 +34,7 @@ from flask_login import current_user from app.entreprises.models import ( Entreprise, - EntrepriseContact, + EntrepriseCorrespondant, EntrepriseOffre, EntrepriseOffreDepartement, EntreprisePreferences, @@ -85,7 +85,9 @@ def get_offre_files_and_depts(offre: EntrepriseOffre, depts: list): Retourne l'offre, les fichiers attachés a l'offre et les département liés """ offre_depts = EntrepriseOffreDepartement.query.filter_by(offre_id=offre.id).all() - contact = EntrepriseContact.query.filter_by(id=offre.contact_id).first() + correspondant = EntrepriseCorrespondant.query.filter_by( + id=offre.correspondant_id + ).first() if not offre_depts or check_offre_depts(depts, offre_depts): files = [] path = os.path.join( @@ -101,12 +103,12 @@ def get_offre_files_and_depts(offre: EntrepriseOffre, depts: list): for _file in glob.glob(f"{dir}/*"): file = [os.path.basename(dir), os.path.basename(_file)] files.append(file) - return [offre, files, offre_depts, contact] + return [offre, files, offre_depts, correspondant] return None def send_email_notifications_entreprise( - subject, entreprise: Entreprise, contact: EntrepriseContact + subject, entreprise: Entreprise, correspondant: EntrepriseCorrespondant ): txt = [ "Une entreprise est en attente de validation", @@ -118,13 +120,13 @@ def send_email_notifications_entreprise( f"\tville: {entreprise.ville}", f"\tpays: {entreprise.pays}", "", - "Contact:", - f"nom: {contact.nom}", - f"prenom: {contact.prenom}", - f"telephone: {contact.telephone}", - f"mail: {contact.mail}", - f"poste: {contact.poste}", - f"service: {contact.service}", + "Correspondant:", + f"nom: {correspondant.nom}", + f"prenom: {correspondant.prenom}", + f"telephone: {correspondant.telephone}", + f"mail: {correspondant.mail}", + f"poste: {correspondant.poste}", + f"service: {correspondant.service}", ] txt = "\n".join(txt) email.send_email( @@ -136,34 +138,42 @@ def send_email_notifications_entreprise( return txt -def verif_contact_data(contact_data): +def verif_correspondant_data(correspondant_data): """ - Verifie les données d'une ligne Excel (contact) - contact_data[0]: nom - contact_data[1]: prenom - contact_data[2]: telephone - contact_data[3]: mail - contact_data[4]: poste - contact_data[5]: service - contact_data[6]: entreprise_id + Verifie les données d'une ligne Excel (correspondant) + correspondant_data[0]: nom + correspondant_data[1]: prenom + correspondant_data[2]: telephone + correspondant_data[3]: mail + correspondant_data[4]: poste + correspondant_data[5]: service + correspondant_data[6]: entreprise_id """ # champs obligatoires - if contact_data[0] == "" or contact_data[1] == "" or contact_data[6] == "": + if ( + correspondant_data[0] == "" + or correspondant_data[1] == "" + or correspondant_data[6] == "" + ): return False # entreprise_id existant - entreprise = Entreprise.query.filter_by(siret=contact_data[6]).first() + entreprise = Entreprise.query.filter_by(siret=correspondant_data[6]).first() if entreprise is None: return False - # contact possède le meme nom et prénom dans la meme entreprise - contact = EntrepriseContact.query.filter_by( - nom=contact_data[0], prenom=contact_data[1], entreprise_id=entreprise.id + # correspondant possède le meme nom et prénom dans la meme entreprise + correspondant = EntrepriseCorrespondant.query.filter_by( + nom=correspondant_data[0], + prenom=correspondant_data[1], + entreprise_id=entreprise.id, ).first() - if contact is not None: + if correspondant is not None: return False - if contact_data[2] == "" and contact_data[3] == "": # 1 moyen de contact + if ( + correspondant_data[2] == "" and correspondant_data[3] == "" + ): # 1 moyen de contact return False return True @@ -189,10 +199,10 @@ def verif_entreprise_data(entreprise_data): req = requests.get( f"https://entreprise.data.gouv.fr/api/sirene/v1/siret/{siret}" ) + if req.status_code != 200: + return False except requests.ConnectionError: print("no internet") - if req.status_code != 200: - return False entreprise = Entreprise.query.filter_by(siret=siret).first() if entreprise is not None: return False diff --git a/app/entreprises/forms.py b/app/entreprises/forms.py index 19719bcc..67b6a0f2 100644 --- a/app/entreprises/forms.py +++ b/app/entreprises/forms.py @@ -44,7 +44,11 @@ from wtforms import ( from wtforms.validators import ValidationError, DataRequired, Email, Optional from wtforms.widgets import ListWidget, CheckboxInput -from app.entreprises.models import Entreprise, EntrepriseContact, EntreprisePreferences +from app.entreprises.models import ( + Entreprise, + EntrepriseCorrespondant, + EntreprisePreferences, +) from app.models import Identite, Departement from app.auth.models import User @@ -74,15 +78,15 @@ class EntrepriseCreationForm(FlaskForm): ville = _build_string_field("Ville de l'entreprise (*)") pays = _build_string_field("Pays de l'entreprise", required=False) - nom_contact = _build_string_field("Nom du contact (*)") - prenom_contact = _build_string_field("Prénom du contact (*)") - telephone = _build_string_field("Téléphone du contact (*)", required=False) + nom_correspondant = _build_string_field("Nom du correspondant (*)") + prenom_correspondant = _build_string_field("Prénom du correspondant (*)") + telephone = _build_string_field("Téléphone du correspondant (*)", required=False) mail = StringField( - "Mail du contact (*)", + "Mail du correspondant (*)", validators=[Optional(), Email(message="Adresse e-mail invalide")], ) - poste = _build_string_field("Poste du contact", required=False) - service = _build_string_field("Service du contact", required=False) + poste = _build_string_field("Poste du correspondant", required=False) + service = _build_string_field("Service du correspondant", required=False) submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE) def validate(self): @@ -108,10 +112,10 @@ class EntrepriseCreationForm(FlaskForm): req = requests.get( f"https://entreprise.data.gouv.fr/api/sirene/v1/siret/{siret}" ) + if req.status_code != 200: + raise ValidationError("SIRET inexistant") except requests.ConnectionError: print("no internet") - if req.status_code != 200: - raise ValidationError("SIRET inexistant") entreprise = Entreprise.query.filter_by(siret=siret).first() if entreprise is not None: lien = f'ici' @@ -160,15 +164,15 @@ class OffreCreationForm(FlaskForm): duree = _build_string_field("Durée (*)") depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) expiration_date = DateField("Date expiration", validators=[Optional()]) - contact = SelectField("Contact à contacté (*)", validators=[Optional()]) + correspondant = SelectField("Correspondant à contacté (*)", validators=[Optional()]) submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.contact.choices = [ - (contact.id, f"{contact.nom} {contact.prenom}") - for contact in EntrepriseContact.query.filter_by( + self.correspondant.choices = [ + (correspondant.id, f"{correspondant.nom} {correspondant.prenom}") + for correspondant in EntrepriseCorrespondant.query.filter_by( entreprise_id=self.hidden_entreprise_id.data ) ] @@ -195,15 +199,15 @@ class OffreModificationForm(FlaskForm): duree = _build_string_field("Durée (*)") depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) expiration_date = DateField("Date expiration", validators=[Optional()]) - contact = SelectField("Contact à contacté (*)", validators=[Optional()]) + correspondant = SelectField("Correspondant à contacté (*)", validators=[Optional()]) submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.contact.choices = [ - (contact.id, f"{contact.nom} {contact.prenom}") - for contact in EntrepriseContact.query.filter_by( + self.correspondant.choices = [ + (correspondant.id, f"{correspondant.nom} {correspondant.prenom}") + for correspondant in EntrepriseCorrespondant.query.filter_by( entreprise_id=self.hidden_entreprise_id.data ) ] @@ -213,7 +217,7 @@ class OffreModificationForm(FlaskForm): ] -class ContactCreationForm(FlaskForm): +class CorrespondantCreationForm(FlaskForm): hidden_entreprise_id = HiddenField() nom = _build_string_field("Nom (*)") prenom = _build_string_field("Prénom (*)") @@ -239,13 +243,13 @@ class ContactCreationForm(FlaskForm): if not FlaskForm.validate(self): validate = False - contact = EntrepriseContact.query.filter_by( + correspondant = EntrepriseCorrespondant.query.filter_by( entreprise_id=self.hidden_entreprise_id.data, nom=self.nom.data, prenom=self.prenom.data, ).first() - if contact is not None: - self.nom.errors.append("Ce contact existe déjà (même nom et prénom)") + if correspondant is not None: + self.nom.errors.append("Ce correspondant existe déjà (même nom et prénom)") self.prenom.errors.append("") validate = False @@ -259,8 +263,8 @@ class ContactCreationForm(FlaskForm): return validate -class ContactModificationForm(FlaskForm): - hidden_contact_id = HiddenField() +class CorrespondantModificationForm(FlaskForm): + hidden_correspondant_id = HiddenField() hidden_entreprise_id = HiddenField() nom = _build_string_field("Nom (*)") prenom = _build_string_field("Prénom (*)") @@ -286,14 +290,14 @@ class ContactModificationForm(FlaskForm): if not FlaskForm.validate(self): validate = False - contact = EntrepriseContact.query.filter( - EntrepriseContact.id != self.hidden_contact_id.data, - EntrepriseContact.entreprise_id == self.hidden_entreprise_id.data, - EntrepriseContact.nom == self.nom.data, - EntrepriseContact.prenom == self.prenom.data, + correspondant = EntrepriseCorrespondant.query.filter( + EntrepriseCorrespondant.id != self.hidden_correspondant_id.data, + EntrepriseCorrespondant.entreprise_id == self.hidden_entreprise_id.data, + EntrepriseCorrespondant.nom == self.nom.data, + EntrepriseCorrespondant.prenom == self.prenom.data, ).first() - if contact is not None: - self.nom.errors.append("Ce contact existe déjà (même nom et prénom)") + if correspondant is not None: + self.nom.errors.append("Ce correspondant existe déjà (même nom et prénom)") self.prenom.errors.append("") validate = False @@ -307,7 +311,7 @@ class ContactModificationForm(FlaskForm): return validate -class HistoriqueCreationForm(FlaskForm): +class StageApprentissageCreationForm(FlaskForm): etudiant = _build_string_field( "Étudiant (*)", render_kw={"placeholder": "Tapez le nom de l'étudiant"}, @@ -353,6 +357,52 @@ class HistoriqueCreationForm(FlaskForm): raise ValidationError("Champ incorrect (selectionnez dans la liste)") +class StageApprentissageModificationForm(FlaskForm): + etudiant = _build_string_field( + "Étudiant (*)", + render_kw={"placeholder": "Tapez le nom de l'étudiant"}, + ) + type_offre = SelectField( + "Type de l'offre (*)", + choices=[("Stage"), ("Alternance")], + validators=[DataRequired(message=CHAMP_REQUIS)], + ) + date_debut = DateField( + "Date début (*)", validators=[DataRequired(message=CHAMP_REQUIS)] + ) + date_fin = DateField( + "Date fin (*)", validators=[DataRequired(message=CHAMP_REQUIS)] + ) + submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE) + + def validate(self): + validate = True + if not FlaskForm.validate(self): + validate = False + + if ( + self.date_debut.data + and self.date_fin.data + and self.date_debut.data > self.date_fin.data + ): + self.date_debut.errors.append("Les dates sont incompatibles") + self.date_fin.errors.append("Les dates sont incompatibles") + validate = False + + return validate + + def validate_etudiant(self, etudiant): + etudiant_data = etudiant.data.upper().strip() + stm = text( + "SELECT id, CONCAT(nom, ' ', prenom) as nom_prenom FROM Identite WHERE CONCAT(nom, ' ', prenom)=:nom_prenom" + ) + etudiant = ( + Identite.query.from_statement(stm).params(nom_prenom=etudiant_data).first() + ) + if etudiant is None: + raise ValidationError("Champ incorrect (selectionnez dans la liste)") + + class EnvoiOffreForm(FlaskForm): responsable = _build_string_field( "Responsable de formation (*)", diff --git a/app/entreprises/models.py b/app/entreprises/models.py index b4c1e7ca..769836b8 100644 --- a/app/entreprises/models.py +++ b/app/entreprises/models.py @@ -11,8 +11,8 @@ class Entreprise(db.Model): ville = db.Column(db.Text) pays = db.Column(db.Text, default="FRANCE") visible = db.Column(db.Boolean, default=False) - contacts = db.relationship( - "EntrepriseContact", + correspondants = db.relationship( + "EntrepriseCorrespondant", backref="entreprise", lazy="dynamic", cascade="all, delete-orphan", @@ -35,8 +35,8 @@ class Entreprise(db.Model): } -class EntrepriseContact(db.Model): - __tablename__ = "are_contacts" +class EntrepriseCorrespondant(db.Model): + __tablename__ = "are_correspondants" id = db.Column(db.Integer, primary_key=True) entreprise_id = db.Column( db.Integer, db.ForeignKey("are_entreprises.id", ondelete="cascade") @@ -75,8 +75,8 @@ class EntrepriseOffre(db.Model): duree = db.Column(db.Text) expiration_date = db.Column(db.Date) expired = db.Column(db.Boolean, default=False) - contact_id = db.Column( - db.Integer, db.ForeignKey("are_contacts.id", ondelete="cascade") + correspondant_id = db.Column( + db.Integer, db.ForeignKey("are_correspondants.id", ondelete="cascade") ) def to_dict(self): @@ -98,8 +98,8 @@ class EntrepriseLog(db.Model): text = db.Column(db.Text) -class EntrepriseEtudiant(db.Model): - __tablename__ = "are_etudiants" +class EntrepriseStageApprentissage(db.Model): + __tablename__ = "are_stages_apprentissages" id = db.Column(db.Integer, primary_key=True) entreprise_id = db.Column( db.Integer, db.ForeignKey("are_entreprises.id", ondelete="cascade") @@ -139,11 +139,11 @@ class EntrepriseOffreDepartement(db.Model): dept_id = db.Column(db.Integer, db.ForeignKey("departement.id", ondelete="cascade")) -# class EntrepriseContactDepartement(db.Model): -# __tablename__ = "are_contact_departement" +# class EntrepriseCorrespondantDepartement(db.Model): +# __tablename__ = "are_correspondant_departement" # id = db.Column(db.Integer, primary_key=True) -# contact_id = db.Column( -# db.Integer, db.ForeignKey("are_contacts.id", ondelete="cascade") +# correspondant_id = db.Column( +# db.Integer, db.ForeignKey("are_correspondants.id", ondelete="cascade") # ) # dept_id = db.Column(db.Integer, db.ForeignKey("departement.id", ondelete="cascade")) diff --git a/app/entreprises/routes.py b/app/entreprises/routes.py index 281ad047..bc6564eb 100644 --- a/app/entreprises/routes.py +++ b/app/entreprises/routes.py @@ -17,9 +17,10 @@ from app.entreprises.forms import ( SuppressionConfirmationForm, OffreCreationForm, OffreModificationForm, - ContactCreationForm, - ContactModificationForm, - HistoriqueCreationForm, + CorrespondantCreationForm, + CorrespondantModificationForm, + StageApprentissageCreationForm, + StageApprentissageModificationForm, EnvoiOffreForm, AjoutFichierForm, ValidationConfirmationForm, @@ -30,9 +31,9 @@ from app.entreprises import bp from app.entreprises.models import ( Entreprise, EntrepriseOffre, - EntrepriseContact, + EntrepriseCorrespondant, EntrepriseLog, - EntrepriseEtudiant, + EntrepriseStageApprentissage, EntrepriseEnvoiOffre, EntrepriseOffreDepartement, EntreprisePreferences, @@ -96,22 +97,22 @@ def validation(): ) -@bp.route("/contacts", methods=["GET"]) +@bp.route("/correspondants", methods=["GET"]) @permission_required(Permission.RelationsEntreprisesView) -def contacts(): +def correspondants(): """ - Permet d'afficher une page avec la liste des contacts des entreprises visibles et une liste des dernières opérations + Permet d'afficher une page avec la liste des correspondants des entreprises visibles et une liste des dernières opérations """ - contacts = ( - db.session.query(EntrepriseContact, Entreprise) - .join(Entreprise, EntrepriseContact.entreprise_id == Entreprise.id) + correspondants = ( + db.session.query(EntrepriseCorrespondant, Entreprise) + .join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id) .filter_by(visible=True) ) logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all() return render_template( - "entreprises/contacts.html", - title="Contacts", - contacts=contacts, + "entreprises/correspondants.html", + title="Correspondants", + correspondants=correspondants, logs=logs, ) @@ -122,7 +123,7 @@ def fiche_entreprise(id): """ Permet d'afficher la fiche entreprise d'une entreprise avec une liste des dernières opérations et l'historique des étudiants ayant réaliser un stage ou une alternance dans cette entreprise. - La fiche entreprise comporte les informations de l'entreprise, les contacts de l'entreprise et + La fiche entreprise comporte les informations de l'entreprise, les correspondants de l'entreprise et les offres de l'entreprise. """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( @@ -141,28 +142,28 @@ def fiche_entreprise(id): offre_with_files = are.get_offre_files_and_depts(offre, depts) if offre_with_files is not None: offres_with_files.append(offre_with_files) - contacts = entreprise.contacts[:] + correspondants = entreprise.correspondants[:] logs = ( EntrepriseLog.query.order_by(EntrepriseLog.date.desc()) .filter_by(object=id) .limit(LOGS_LEN) .all() ) - historique = ( - db.session.query(EntrepriseEtudiant, Identite) - .order_by(EntrepriseEtudiant.date_debut.desc()) - .filter(EntrepriseEtudiant.entreprise_id == id) - .join(Identite, Identite.id == EntrepriseEtudiant.etudid) + stages_apprentissages = ( + db.session.query(EntrepriseStageApprentissage, Identite) + .order_by(EntrepriseStageApprentissage.date_debut.desc()) + .filter(EntrepriseStageApprentissage.entreprise_id == id) + .join(Identite, Identite.id == EntrepriseStageApprentissage.etudid) .all() ) return render_template( "entreprises/fiche_entreprise.html", title="Fiche entreprise", entreprise=entreprise, - contacts=contacts, + correspondants=correspondants, offres=offres_with_files, logs=logs, - historique=historique, + stages_apprentissages=stages_apprentissages, ) @@ -198,12 +199,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" ) - contacts = entreprise.contacts + correspondants = entreprise.correspondants return render_template( "entreprises/fiche_entreprise_validation.html", title="Validation fiche entreprise", entreprise=entreprise, - contacts=contacts, + correspondants=correspondants, ) @@ -221,7 +222,9 @@ def offres_recues(): ) offres_recues_with_files = [] for offre in offres_recues: - contact = EntrepriseContact.query.filter_by(id=offre[1].contact_id).first() + correspondant = EntrepriseCorrespondant.query.filter_by( + id=offre[1].correspondant_id + ).first() files = [] path = os.path.join( Config.SCODOC_VAR_DIR, @@ -236,7 +239,7 @@ def offres_recues(): for file in glob.glob(f"{dir}/*"): file = [os.path.basename(dir), os.path.basename(file)] files.append(file) - offres_recues_with_files.append([offre[0], offre[1], files, contact]) + offres_recues_with_files.append([offre[0], offre[1], files, correspondant]) return render_template( "entreprises/offres_recues.html", title="Offres reçues", @@ -289,22 +292,22 @@ def add_entreprise(): db.session.add(entreprise) db.session.commit() db.session.refresh(entreprise) - contact = EntrepriseContact( + correspondant = EntrepriseCorrespondant( entreprise_id=entreprise.id, - nom=form.nom_contact.data.strip(), - prenom=form.prenom_contact.data.strip(), + nom=form.nom_correspondant.data.strip(), + prenom=form.prenom_correspondant.data.strip(), telephone=form.telephone.data.strip(), mail=form.mail.data.strip(), poste=form.poste.data.strip(), service=form.service.data.strip(), ) - db.session.add(contact) + db.session.add(correspondant) if current_user.has_permission(Permission.RelationsEntreprisesValidate, None): entreprise.visible = True nom_entreprise = f"{entreprise.nom}" log = EntrepriseLog( authenticated_user=current_user.user_name, - text=f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom}) avec un contact", + text=f"{nom_entreprise} - Création de la fiche entreprise ({entreprise.nom}) avec un correspondant", ) db.session.add(log) db.session.commit() @@ -315,13 +318,13 @@ def add_entreprise(): db.session.commit() if EntreprisePreferences.get_email_notifications(): are.send_email_notifications_entreprise( - "entreprise en attente de validation", entreprise, contact + "entreprise en attente de validation", entreprise, correspondant ) flash("L'entreprise a été ajouté à la liste pour la validation.") return redirect(url_for("entreprises.index")) return render_template( "entreprises/ajout_entreprise.html", - title="Ajout entreprise avec contact", + title="Ajout entreprise avec correspondant", form=form, ) @@ -448,7 +451,7 @@ def validate_entreprise(id): nom_entreprise = f"{entreprise.nom}" log = EntrepriseLog( authenticated_user=current_user.user_name, - text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom}) avec un contact", + text=f"{nom_entreprise} - Validation de la fiche entreprise ({entreprise.nom}) avec un correspondant", ) db.session.add(log) db.session.commit() @@ -502,7 +505,7 @@ def add_offre(id): missions=form.missions.data.strip(), duree=form.duree.data.strip(), expiration_date=form.expiration_date.data, - contact_id=form.contact.data, + correspondant_id=form.correspondant.data, ) db.session.add(offre) db.session.commit() @@ -540,18 +543,17 @@ def edit_offre(id): ) offre_depts = EntrepriseOffreDepartement.query.filter_by(offre_id=offre.id).all() form = OffreModificationForm( - hidden_entreprise_id=offre.entreprise_id, contact=offre.contact_id + hidden_entreprise_id=offre.entreprise_id, correspondant=offre.correspondant_id ) offre_depts_list = [(offre_dept.dept_id) for offre_dept in offre_depts] if form.validate_on_submit(): - print(form.contact.data) offre.intitule = form.intitule.data.strip() offre.description = form.description.data.strip() offre.type_offre = form.type_offre.data.strip() offre.missions = form.missions.data.strip() offre.duree = form.duree.data.strip() offre.expiration_date = form.expiration_date.data - offre.contact_id = form.contact.data + offre.correspondant_id = form.correspondant.data if offre_depts_list != form.depts.data: for dept in form.depts.data: if dept not in offre_depts_list: @@ -659,18 +661,18 @@ def expired(id): return redirect(url_for("entreprises.fiche_entreprise", id=offre.entreprise_id)) -@bp.route("/add_contact/", methods=["GET", "POST"]) +@bp.route("/add_correspondant/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) -def add_contact(id): +def add_correspondant(id): """ - Permet d'ajouter un contact a une entreprise + Permet d'ajouter un correspondant a une entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) - form = ContactCreationForm(hidden_entreprise_id=entreprise.id) + form = CorrespondantCreationForm(hidden_entreprise_id=entreprise.id) if form.validate_on_submit(): - contact = EntrepriseContact( + correspondant = EntrepriseCorrespondant( entreprise_id=entreprise.id, nom=form.nom.data.strip(), prenom=form.prenom.data.strip(), @@ -682,116 +684,116 @@ def add_contact(id): log = EntrepriseLog( authenticated_user=current_user.user_name, object=entreprise.id, - text="Création d'un contact", + text="Création d'un correspondant", ) db.session.add(log) - db.session.add(contact) + db.session.add(correspondant) db.session.commit() - flash("Le contact a été ajouté à la fiche entreprise.") + flash("Le correspondant a été ajouté à la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return render_template( "entreprises/form.html", - title="Ajout contact", + title="Ajout correspondant", form=form, ) -@bp.route("/edit_contact/", methods=["GET", "POST"]) +@bp.route("/edit_correspondant/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) -def edit_contact(id): +def edit_correspondant(id): """ - Permet de modifier un contact + Permet de modifier un correspondant """ - contact = EntrepriseContact.query.filter_by(id=id).first_or_404( - description=f"contact {id} inconnu" + correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404( + description=f"correspondant {id} inconnu" ) - form = ContactModificationForm( - hidden_entreprise_id=contact.entreprise_id, - hidden_contact_id=contact.id, + form = CorrespondantModificationForm( + hidden_entreprise_id=correspondant.entreprise_id, + hidden_correspondant_id=correspondant.id, ) if form.validate_on_submit(): - contact.nom = form.nom.data.strip() - contact.prenom = form.prenom.data.strip() - contact.telephone = form.telephone.data.strip() - contact.mail = form.mail.data.strip() - contact.poste = form.poste.data.strip() - contact.service = form.service.data.strip() + correspondant.nom = form.nom.data.strip() + correspondant.prenom = form.prenom.data.strip() + correspondant.telephone = form.telephone.data.strip() + correspondant.mail = form.mail.data.strip() + correspondant.poste = form.poste.data.strip() + correspondant.service = form.service.data.strip() log = EntrepriseLog( authenticated_user=current_user.user_name, - object=contact.entreprise_id, - text="Modification d'un contact", + object=correspondant.entreprise_id, + text="Modification d'un correspondant", ) db.session.add(log) db.session.commit() - flash("Le contact a été modifié.") + flash("Le correspondant a été modifié.") return redirect( - url_for("entreprises.fiche_entreprise", id=contact.entreprise.id) + url_for("entreprises.fiche_entreprise", id=correspondant.entreprise.id) ) elif request.method == "GET": - form.nom.data = contact.nom - form.prenom.data = contact.prenom - form.telephone.data = contact.telephone - form.mail.data = contact.mail - form.poste.data = contact.poste - form.service.data = contact.service + form.nom.data = correspondant.nom + form.prenom.data = correspondant.prenom + form.telephone.data = correspondant.telephone + form.mail.data = correspondant.mail + form.poste.data = correspondant.poste + form.service.data = correspondant.service return render_template( "entreprises/form.html", - title="Modification contact", + title="Modification correspondant", form=form, ) -@bp.route("/delete_contact/", methods=["GET", "POST"]) +@bp.route("/delete_correspondant/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) -def delete_contact(id): +def delete_correspondant(id): """ - Permet de supprimer un contact + Permet de supprimer un correspondant """ - contact = EntrepriseContact.query.filter_by(id=id).first_or_404( - description=f"contact {id} inconnu" + correspondant = EntrepriseCorrespondant.query.filter_by(id=id).first_or_404( + description=f"correspondant {id} inconnu" ) form = SuppressionConfirmationForm() if form.validate_on_submit(): - contact_count = EntrepriseContact.query.filter_by( - entreprise_id=contact.entreprise_id + correspondant_count = EntrepriseCorrespondant.query.filter_by( + entreprise_id=correspondant.entreprise_id ).count() - if contact_count == 1: + if correspondant_count == 1: flash( - "Le contact n'a pas été supprimé de la fiche entreprise. (1 contact minimum)" + "Le correspondant n'a pas été supprimé de la fiche entreprise. (1 correspondant minimum)" ) return redirect( - url_for("entreprises.fiche_entreprise", id=contact.entreprise_id) + url_for("entreprises.fiche_entreprise", id=correspondant.entreprise_id) ) else: - db.session.delete(contact) + db.session.delete(correspondant) log = EntrepriseLog( authenticated_user=current_user.user_name, - object=contact.entreprise_id, - text="Suppression d'un contact", + object=correspondant.entreprise_id, + text="Suppression d'un correspondant", ) db.session.add(log) db.session.commit() - flash("Le contact a été supprimé de la fiche entreprise.") + flash("Le correspondant a été supprimé de la fiche entreprise.") return redirect( - url_for("entreprises.fiche_entreprise", id=contact.entreprise_id) + url_for("entreprises.fiche_entreprise", id=correspondant.entreprise_id) ) return render_template( "entreprises/delete_confirmation.html", - title="Supression contact", + title="Supression correspondant", form=form, ) -@bp.route("/add_historique/", methods=["GET", "POST"]) +@bp.route("/add_stages_apprentissages/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) -def add_historique(id): +def add_stages_apprentissages(id): """ Permet d'ajouter un étudiant ayant réalisé un stage ou une alternance sur la fiche entreprise de l'entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) - form = HistoriqueCreationForm() + form = StageApprentissageCreationForm() if form.validate_on_submit(): etudiant_nomcomplet = form.etudiant.data.upper().strip() stm = text( @@ -805,7 +807,7 @@ def add_historique(id): formation = etudiant.inscription_courante_date( form.date_debut.data, form.date_fin.data ) - historique = EntrepriseEtudiant( + stage_apprentissage = EntrepriseStageApprentissage( entreprise_id=entreprise.id, etudid=etudiant.id, type_offre=form.type_offre.data.strip(), @@ -816,13 +818,64 @@ def add_historique(id): if formation else None, ) - db.session.add(historique) + db.session.add(stage_apprentissage) db.session.commit() flash("L'étudiant a été ajouté sur la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) return render_template( - "entreprises/ajout_historique.html", - title="Ajout historique", + "entreprises/ajout_stage_apprentissage.html", + title="Ajout stage / apprentissage", + form=form, + ) + + +@bp.route("/edit_stages_apprentissages/", methods=["GET", "POST"]) +@permission_required(Permission.RelationsEntreprisesChange) +def edit_stages_apprentissages(id): + stage_apprentissage = EntrepriseStageApprentissage.query.filter_by( + id=id + ).first_or_404(description=f"stage_apprentissage {id} inconnue") + etudiant = Identite.query.filter_by(id=stage_apprentissage.etudid).first_or_404( + description=f"etudiant {id} inconnue" + ) + form = StageApprentissageModificationForm() + if form.validate_on_submit(): + etudiant_nomcomplet = form.etudiant.data.upper().strip() + stm = text( + "SELECT id, CONCAT(nom, ' ', prenom) as nom_prenom FROM Identite WHERE CONCAT(nom, ' ', prenom)=:nom_prenom" + ) + etudiant = ( + Identite.query.from_statement(stm) + .params(nom_prenom=etudiant_nomcomplet) + .first() + ) + formation = etudiant.inscription_courante_date( + form.date_debut.data, form.date_fin.data + ) + stage_apprentissage.etudid = etudiant.id + stage_apprentissage.type_offre = form.type_offre.data.strip() + stage_apprentissage.date_debut = (form.date_debut.data,) + stage_apprentissage.date_fin = (form.date_fin.data,) + stage_apprentissage.formation_text = ( + formation.formsemestre.titre if formation else None, + ) + stage_apprentissage.formation_scodoc = ( + formation.formsemestre.formsemestre_id if formation else None, + ) + db.session.commit() + return redirect( + url_for( + "entreprises.fiche_entreprise", id=stage_apprentissage.entreprise_id + ) + ) + elif request.method == "GET": + form.etudiant.data = f"{sco_etud.format_nom(etudiant.nom)} {sco_etud.format_prenom(etudiant.prenom)}" + form.type_offre.data = stage_apprentissage.type_offre + form.date_debut.data = stage_apprentissage.date_debut + form.date_fin.data = stage_apprentissage.date_fin + return render_template( + "entreprises/ajout_stage_apprentissage.html", + title="Modification stage / apprentissage", form=form, ) @@ -1032,19 +1085,19 @@ def import_entreprises(): ) -@bp.route("/export_contacts") +@bp.route("/export_correspondants") @permission_required(Permission.RelationsEntreprisesExport) -def export_contacts(): +def export_correspondants(): """ - Permet d'exporter la liste des contacts sous format excel (.xlsx) + Permet d'exporter la liste des correspondants sous format excel (.xlsx) """ - contacts = ( - db.session.query(EntrepriseContact) - .join(Entreprise, EntrepriseContact.entreprise_id == Entreprise.id) + correspondants = ( + db.session.query(EntrepriseCorrespondant) + .join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id) .filter_by(visible=True) .all() ) - if contacts: + if correspondants: keys = [ "nom", "prenom", @@ -1055,8 +1108,11 @@ def export_contacts(): "entreprise_siret", ] titles = keys[:] - L = [[contact.to_dict().get(k, "") for k in keys] for contact in contacts] - title = "Contacts" + 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) @@ -1064,11 +1120,11 @@ def export_contacts(): abort(404) -@bp.route("/get_import_contacts_file_sample") +@bp.route("/get_import_correspondants_file_sample") @permission_required(Permission.RelationsEntreprisesExport) -def get_import_contacts_file_sample(): +def get_import_correspondants_file_sample(): """ - Permet de récupérer un fichier exemple vide pour pouvoir importer des contacts + Permet de récupérer un fichier exemple vide pour pouvoir importer des correspondants """ keys = [ "nom", @@ -1080,17 +1136,17 @@ def get_import_contacts_file_sample(): "entreprise_siret", ] titles = keys[:] - title = "ImportContacts" - xlsx = sco_excel.excel_simple_table(titles=titles, sheet_name="Contacts") + 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_contacts", methods=["GET", "POST"]) +@bp.route("/import_correspondants", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesExport) -def import_contacts(): +def import_correspondants(): """ - Permet d'importer des contacts a l'aide d'un fichier excel (.xlsx) + Permet d'importer des correspondants a l'aide d'un fichier excel (.xlsx) """ form = ImportForm() if form.validate_on_submit(): @@ -1101,8 +1157,8 @@ def import_contacts(): file.save(file_path) data = sco_excel.excel_file_to_list(file_path) os.remove(file_path) - contacts_import = [] - contact_list = [] + correspondants_import = [] + correspondant_list = [] ligne = 0 titles = [ "nom", @@ -1116,57 +1172,69 @@ def import_contacts(): if data[1][0] != titles: flash("Veuillez utilisez la feuille excel à remplir") return render_template( - "entreprises/import_contacts.html", - title="Importation contacts", + "entreprises/import_correspondants.html", + title="Importation correspondants", form=form, ) - for contact_data in data[1][1:]: + for correspondant_data in data[1][1:]: ligne += 1 if ( - are.verif_contact_data(contact_data) - and (contact_data[0], contact_data[1], contact_data[6]) - not in contact_list - ): - contact_list.append((contact_data[0], contact_data[1], contact_data[6])) - contact = EntrepriseContact( - nom=contact_data[0], - prenom=contact_data[1], - telephone=contact_data[2], - mail=contact_data[3], - poste=contact_data[4], - service=contact_data[5], - entreprise_id=contact_data[6], + are.verif_correspondant_data(correspondant_data) + and ( + correspondant_data[0], + correspondant_data[1], + correspondant_data[6], ) - contacts_import.append(contact) + not in correspondant_list + ): + correspondant_list.append( + ( + correspondant_data[0], + correspondant_data[1], + correspondant_data[6], + ) + ) + correspondant = EntrepriseCorrespondant( + nom=correspondant_data[0], + prenom=correspondant_data[1], + telephone=correspondant_data[2], + mail=correspondant_data[3], + poste=correspondant_data[4], + service=correspondant_data[5], + entreprise_id=correspondant_data[6], + ) + correspondants_import.append(correspondant) else: flash(f"Erreur lors de l'importation (ligne {ligne})") return render_template( - "entreprises/import_contacts.html", - title="Importation contacts", + "entreprises/import_correspondants.html", + title="Importation correspondants", form=form, ) - if len(contacts_import) > 0: - for contact in contacts_import: - db.session.add(contact) + 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(contacts_import)} contact(s)", + text=f"Importation de {len(correspondants_import)} correspondant(s)", ) db.session.add(log) db.session.commit() - flash(f"Importation réussie de {len(contacts_import)} contact(s)") + flash( + f"Importation réussie de {len(correspondants_import)} correspondant(s)" + ) return render_template( - "entreprises/import_contacts.html", - title="Importation Contacts", + "entreprises/import_correspondants.html", + title="Importation correspondants", form=form, - contacts_import=contacts_import, + correspondants_import=correspondants_import, ) else: - flash('Feuille "Contacts" vide') + flash('Feuille "Correspondants" vide') return render_template( - "entreprises/import_contacts.html", - title="Importation contacts", + "entreprises/import_correspondants.html", + title="Importation correspondants", form=form, ) diff --git a/app/static/css/entreprises.css b/app/static/css/entreprises.css index fac9d11b..3193527d 100644 --- a/app/static/css/entreprises.css +++ b/app/static/css/entreprises.css @@ -50,23 +50,23 @@ margin-bottom: -5px; } -.entreprise, .contact, .offre { +.entreprise, .correspondant, .offre { border: solid 2px; border-radius: 10px; padding: 10px; margin-bottom: 10px; } -.contacts-et-offres { +.correspondants-et-offres { display: flex; justify-content: space-between; } -.contacts-et-offres > div { +.correspondants-et-offres > div { flex: 1 0 0; } -.contacts-et-offres > div:nth-child(2) { +.correspondants-et-offres > div:nth-child(2) { margin-left: 20px; } diff --git a/app/templates/entreprises/_contact.html b/app/templates/entreprises/_contact.html deleted file mode 100644 index e2f61aa9..00000000 --- a/app/templates/entreprises/_contact.html +++ /dev/null @@ -1,26 +0,0 @@ -{# -*- mode: jinja-html -*- #} -
-
- Nom : {{ contact.nom }}
- Prénom : {{ contact.prenom }}
- {% if contact.telephone %} - Téléphone : {{ contact.telephone }}
- {% endif %} - {% if contact.mail %} - Mail : {{ contact.mail }}
- {% endif %} - {% if contact.poste %} - Poste : {{ contact.poste }}
- {% endif %} - {% if contact.service %} - Service : {{ contact.service }}
- {% endif %} -
- - {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} - - {% endif %} -
\ No newline at end of file diff --git a/app/templates/entreprises/_correspondant.html b/app/templates/entreprises/_correspondant.html new file mode 100644 index 00000000..0def6b89 --- /dev/null +++ b/app/templates/entreprises/_correspondant.html @@ -0,0 +1,26 @@ +{# -*- mode: jinja-html -*- #} +
+
+ Nom : {{ correspondant.nom }}
+ Prénom : {{ correspondant.prenom }}
+ {% if correspondant.telephone %} + Téléphone : {{ correspondant.telephone }}
+ {% endif %} + {% if correspondant.mail %} + Mail : {{ correspondant.mail }}
+ {% endif %} + {% if correspondant.poste %} + Poste : {{ correspondant.poste }}
+ {% endif %} + {% if correspondant.service %} + Service : {{ correspondant.service }}
+ {% endif %} +
+ + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} + + {% endif %} +
\ No newline at end of file diff --git a/app/templates/entreprises/_offre.html b/app/templates/entreprises/_offre.html index 11391da3..c900a2fa 100644 --- a/app/templates/entreprises/_offre.html +++ b/app/templates/entreprises/_offre.html @@ -10,7 +10,7 @@ Département(s) : {% for offre_dept in offre[2] %}
{{ offre_dept.dept_id|get_dept_acronym }}
{% endfor %}
{% endif %} - {% if offre[0].contact_id %} + {% if offre[0].correspondant_id %} Contacté {{ offre[3].nom }} {{ offre[3].prenom }} {% if offre[3].mail and offre[3].telephone %} ({{ offre[3].mail }} - {{ offre[3].telephone }})
diff --git a/app/templates/entreprises/ajout_entreprise.html b/app/templates/entreprises/ajout_entreprise.html index 0eead428..f940097a 100644 --- a/app/templates/entreprises/ajout_entreprise.html +++ b/app/templates/entreprises/ajout_entreprise.html @@ -3,7 +3,7 @@ {% import 'bootstrap/wtf.html' as wtf %} {% block app_content %} -

Ajout entreprise avec contact

+

Ajout entreprise avec correspondant


diff --git a/app/templates/entreprises/ajout_historique.html b/app/templates/entreprises/ajout_stage_apprentissage.html similarity index 97% rename from app/templates/entreprises/ajout_historique.html rename to app/templates/entreprises/ajout_stage_apprentissage.html index 678d3a72..8055850f 100644 --- a/app/templates/entreprises/ajout_historique.html +++ b/app/templates/entreprises/ajout_stage_apprentissage.html @@ -9,7 +9,7 @@ {% endblock %} {% block app_content %} -

Ajout historique

+

{{ title }}


diff --git a/app/templates/entreprises/contacts.html b/app/templates/entreprises/correspondants.html similarity index 80% rename from app/templates/entreprises/contacts.html rename to app/templates/entreprises/correspondants.html index fa1609ae..94859bb6 100644 --- a/app/templates/entreprises/contacts.html +++ b/app/templates/entreprises/correspondants.html @@ -24,16 +24,16 @@
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %} - Importer des contacts + Importer des correspondants {% endif %} - {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and contacts %} - Exporter la liste des contacts + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and correspondants %} + Exporter la liste des correspondants {% endif %}
-

Liste des contacts

- +

Liste des correspondants

+
@@ -46,15 +46,15 @@ - {% for contact in contacts %} + {% for correspondant in correspondants %} - - - - - - - + + + + + + + {% endfor %} @@ -74,7 +74,7 @@ + + +{% endblock %} + {% block app_content %} {% if logs %}
@@ -15,24 +22,6 @@
{% endif %} - - {% if historique %} -
-

Historique

-
    - {% for data in historique %} -
  • - {{ data[0].date_debut.strftime('%d/%m/%Y') }} - {{ - data[0].date_fin.strftime('%d/%m/%Y') }} - - {{ data[0].type_offre }} réalisé par {{ data[1].nom|format_nom }} {{ data[1].prenom|format_prenom }} - {% if data[0].formation_text %} en {{ data[0].formation_text }}{% endif %} - -
  • - {% endfor %} -
-
- {% endif %}

Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})

@@ -53,20 +42,18 @@ Modifier Supprimer Ajouter offre - Ajouter contact - Ajouter - historique + Ajouter correspondant {% endif %} Voir les offres expirées
-
- {% if contacts %} +
+ {% if correspondants %}
-

Contacts

- {% for contact in contacts %} - {% include 'entreprises/_contact.html' %} +

Correspondants

+ {% for correspondant in correspondants %} + {% include 'entreprises/_correspondant.html' %} {% endfor %}
{% endif %} @@ -81,4 +68,92 @@ {% endif %}
+ +
+ {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} + Ajouter stages ou apprentissages + {% endif %} +

Liste des stages et apprentissages réalisés au sein de l'entreprise

+
Nom
{{ contact[0].nom }}{{ contact[0].prenom }}{{ contact[0].telephone }}{{ contact[0].mail }}{{ contact[0].poste}}{{ contact[0].service}}{{ contact[1].nom }}{{ correspondant[0].nom }}{{ correspondant[0].prenom }}{{ correspondant[0].telephone }}{{ correspondant[0].mail }}{{ correspondant[0].poste}}{{ correspondant[0].service}}{{ correspondant[1].nom }}
+ + + + + + + + + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} + + {% endif %} + + + + {% for data in stages_apprentissages %} + + + + + + + + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} + + {% endif %} + + {% endfor %} + + + + + + + + + + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} + + {% endif %} + + +
Date débutDate finDuréeTypeÉtudiantFormationAction
{{ data[0].date_debut.strftime('%d/%m/%Y') }}{{ data[0].date_fin.strftime('%d/%m/%Y') }}{{(data[0].date_fin-data[0].date_debut).days//7}} semaines{{ data[0].type_offre }}{{ data[1].nom|format_nom }} {{ data[1].prenom|format_prenom }}{% if data[0].formation_text %}{{ data[0].formation_text }}{% endif %} + +
Date débutDate finDuréeTypeÉtudiantFormationAction
+
+ + {% endblock %} \ No newline at end of file diff --git a/app/templates/entreprises/fiche_entreprise_validation.html b/app/templates/entreprises/fiche_entreprise_validation.html index 072461b4..2f243b24 100644 --- a/app/templates/entreprises/fiche_entreprise_validation.html +++ b/app/templates/entreprises/fiche_entreprise_validation.html @@ -16,25 +16,25 @@
- {% if contacts %} + {% if correspondants %}
- {% for contact in contacts %} + {% for correspondant in correspondants %}
-

Contact

-
- Nom : {{ contact.nom }}
- Prénom : {{ contact.prenom }}
- {% if contact.telephone %} - Téléphone : {{ contact.telephone }}
+

Correspondant

+
+ Nom : {{ correspondant.nom }}
+ Prénom : {{ correspondant.prenom }}
+ {% if correspondant.telephone %} + Téléphone : {{ correspondant.telephone }}
{% endif %} - {% if contact.mail %} - Mail : {{ contact.mail }}
+ {% if correspondant.mail %} + Mail : {{ correspondant.mail }}
{% endif %} - {% if contact.poste %} - Poste : {{ contact.poste }}
+ {% if correspondant.poste %} + Poste : {{ correspondant.poste }}
{% endif %} - {% if contact.service %} - Service : {{ contact.service }}
+ {% if correspondant.service %} + Service : {{ correspondant.service }}
{% endif %}
diff --git a/app/templates/entreprises/import_contacts.html b/app/templates/entreprises/import_contacts.html deleted file mode 100644 index 292a0e9f..00000000 --- a/app/templates/entreprises/import_contacts.html +++ /dev/null @@ -1,62 +0,0 @@ -{# -*- mode: jinja-html -*- #} -{% extends 'base.html' %} -{% import 'bootstrap/wtf.html' as wtf %} - -{% block styles %} -{{super()}} -{% endblock %} - -{% block app_content %} -

Importation contacts

-
- -
-
-
-

- (*) champs requis -

- {{ wtf.quick_form(form, novalidate=True) }} -
-
- - {% if not contacts_import %} - - - - - - - - - -
AttributTypeDescription
nomtextnom du contact
prenomtextprenom du contact
telephonetexttelephone du contact
mailtextmail du contact
postetextposte du contact
servicetextservice dans lequel travaille le contact
entreprise_siretintegerSIRET de l'entreprise
- {% endif %} - - {% if contacts_import %} -
Importation de {{ contacts_import|length }} contact(s)
- {% for contact in contacts_import %} -
-
- Nom : {{ contact.nom }}
- Prénom : {{ contact.prenom }}
- {% if contact.telephone %} - Téléphone : {{ contact.telephone }}
- {% endif %} - {% if contact.mail %} - Mail : {{ contact.mail }}
- {% endif %} - {% if contact.poste %} - Poste : {{ contact.poste }}
- {% endif %} - {% if contact.service %} - Service : {{ contact.service }}
- {% endif %} - lien vers l'entreprise -
-
- {% endfor %} - {% endif %} -{% endblock %} \ No newline at end of file diff --git a/app/templates/entreprises/import_correspondants.html b/app/templates/entreprises/import_correspondants.html new file mode 100644 index 00000000..cfbaf11a --- /dev/null +++ b/app/templates/entreprises/import_correspondants.html @@ -0,0 +1,62 @@ +{# -*- mode: jinja-html -*- #} +{% extends 'base.html' %} +{% import 'bootstrap/wtf.html' as wtf %} + +{% block styles %} +{{super()}} +{% endblock %} + +{% block app_content %} +

Importation correspondants

+
+ +
+
+
+

+ (*) champs requis +

+ {{ wtf.quick_form(form, novalidate=True) }} +
+
+ + {% if not correspondants_import %} + + + + + + + + + +
AttributTypeDescription
nomtextnom du correspondant
prenomtextprenom du correspondant
telephonetexttelephone du correspondant
mailtextmail du correspondant
postetextposte du correspondant
servicetextservice dans lequel travaille le correspondant
entreprise_siretintegerSIRET de l'entreprise
+ {% endif %} + + {% if correspondants_import %} +
Importation de {{ correspondants_import|length }} correspondant(s)
+ {% for correspondant in correspondants_import %} +
+
+ Nom : {{ correspondant.nom }}
+ Prénom : {{ correspondant.prenom }}
+ {% if correspondant.telephone %} + Téléphone : {{ correspondant.telephone }}
+ {% endif %} + {% if correspondant.mail %} + Mail : {{ correspondant.mail }}
+ {% endif %} + {% if correspondant.poste %} + Poste : {{ correspondant.poste }}
+ {% endif %} + {% if correspondant.service %} + Service : {{ correspondant.service }}
+ {% endif %} + lien vers l'entreprise +
+
+ {% endfor %} + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/app/templates/entreprises/nav.html b/app/templates/entreprises/nav.html index e2421165..50bca601 100644 --- a/app/templates/entreprises/nav.html +++ b/app/templates/entreprises/nav.html @@ -2,7 +2,7 @@