diff --git a/app/entreprises/__init__.py b/app/entreprises/__init__.py index b211670b..7f100d51 100644 --- a/app/entreprises/__init__.py +++ b/app/entreprises/__init__.py @@ -39,4 +39,12 @@ def get_dept_acronym(id): return dept.acronym +@bp.app_template_filter() +def get_civilité(civ): + if civ == "H": + return "Monsieur" + else: + return "Madame" + + from app.entreprises import routes diff --git a/app/entreprises/app_relations_entreprises.py b/app/entreprises/app_relations_entreprises.py index e3c0d1da..95f1264c 100644 --- a/app/entreprises/app_relations_entreprises.py +++ b/app/entreprises/app_relations_entreprises.py @@ -131,38 +131,46 @@ def send_email_notifications_entreprise(subject, entreprise: Entreprise): def verif_correspondant_data(correspondant_data): """ 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 + 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 """ # champs obligatoires if ( correspondant_data[0].strip() == "" or correspondant_data[1].strip() == "" - or correspondant_data[6].strip() == "" + or correspondant_data[2].strip() == "" + or correspondant_data[9].strip() == "" ): 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[6].strip()).first() + 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[0].strip(), - prenom=correspondant_data[1].strip(), + nom=correspondant_data[1].strip(), + prenom=correspondant_data[2].strip(), entreprise_id=entreprise.id, ).first() if correspondant is not None: return False if ( - correspondant_data[2].strip() == "" and correspondant_data[3].strip() == "" + correspondant_data[3].strip() == "" and correspondant_data[4].strip() == "" ): # 1 moyen de contact return False @@ -182,7 +190,7 @@ def verif_entreprise_data(entreprise_data): if data.strip() == "": return False if EntreprisePreferences.get_check_siret(): - siret = entreprise_data[0].replace(" ", "") # vérification sur le siret + siret = entreprise_data[0].strip().replace(" ", "") # vérification sur le siret if re.match("^\d{14}$", siret) is None: return False try: diff --git a/app/entreprises/forms.py b/app/entreprises/forms.py index 654b2618..a1619007 100644 --- a/app/entreprises/forms.py +++ b/app/entreprises/forms.py @@ -80,6 +80,11 @@ class EntrepriseCreationForm(FlaskForm): ville = _build_string_field("Ville de l'entreprise (*)") pays = _build_string_field("Pays de l'entreprise", required=False) + civilite = SelectField( + "Civilité du correspondant", + choices=[("M", "Monsieur"), ("F", "Madame")], + validators=[DataRequired(message=CHAMP_REQUIS)], + ) nom_correspondant = _build_string_field("Nom du correspondant", required=False) prenom_correspondant = _build_string_field( "Prénom du correspondant", required=False @@ -91,6 +96,8 @@ class EntrepriseCreationForm(FlaskForm): ) poste = _build_string_field("Poste du correspondant", required=False) service = _build_string_field("Service du correspondant", required=False) + origine = _build_string_field("Origine du correspondant", required=False) + notes = _build_string_field("Notes sur le correspondant", required=False) submit = SubmitField("Envoyer", render_kw=SUBMIT_MARGE) @@ -106,6 +113,8 @@ class EntrepriseCreationForm(FlaskForm): or self.mail.data.strip() or self.poste.data.strip() or self.service.data.strip() + or self.origine.data.strip() + or self.notes.data.strip() ): if not self.nom_correspondant.data.strip(): self.nom_correspondant.errors.append("Ce champ est requis") @@ -114,19 +123,16 @@ class EntrepriseCreationForm(FlaskForm): self.prenom_correspondant.errors.append("Ce champ est requis") validate = False if not self.telephone.data.strip() and not self.mail.data.strip(): - self.telephone.errors.append( - "Saisir un moyen de contact (mail ou téléphone)" - ) - self.mail.errors.append( - "Saisir un moyen de contact (mail ou téléphone)" - ) + msg = "Saisir un moyen de contact (mail ou téléphone)" + self.telephone.errors.append(msg) + self.mail.errors.append(msg) validate = False return validate def validate_siret(self, siret): if EntreprisePreferences.get_check_siret(): - siret_data = siret.data.replace(" ", "") + siret_data = siret.data.strip().replace(" ", "") self.siret.data = siret_data if re.match("^\d{14}$", siret_data) is None: raise ValidationError("Format incorrect") @@ -164,6 +170,15 @@ class EntrepriseModificationForm(FlaskForm): } +class SiteCreationForm(FlaskForm): + 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("Envoyer", render_kw=SUBMIT_MARGE) + + class MultiCheckboxField(SelectMultipleField): widget = ListWidget(prefix_label=False) option_widget = CheckboxInput() @@ -184,11 +199,11 @@ class OffreCreationForm(FlaskForm): "Missions (*)", validators=[DataRequired(message=CHAMP_REQUIS)] ) duree = _build_string_field("Durée (*)") - depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) + depts = MultiCheckboxField("Départements (*)", validators=[Optional()], coerce=int) expiration_date = DateField("Date expiration", validators=[Optional()]) correspondant = SelectField("Correspondant à contacté", validators=[Optional()]) fichier = FileField( - "Fichier (*)", + "Fichier", validators=[ Optional(), FileAllowed(["pdf", "docx"], "Fichier .pdf ou .docx uniquement"), @@ -237,7 +252,7 @@ class OffreModificationForm(FlaskForm): "Missions (*)", validators=[DataRequired(message=CHAMP_REQUIS)] ) duree = _build_string_field("Durée (*)") - depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) + depts = MultiCheckboxField("Départements (*)", validators=[Optional()], coerce=int) expiration_date = DateField("Date expiration", validators=[Optional()]) correspondant = SelectField("Correspondant à contacté", validators=[Optional()]) submit = SubmitField("Modifier", render_kw=SUBMIT_MARGE) @@ -269,6 +284,12 @@ class OffreModificationForm(FlaskForm): class CorrespondantCreationForm(FlaskForm): + civilite = SelectField( + "Civilité (*)", + choices=[("H", "Monsieur"), ("F", "Madame")], + 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"}) telephone = _build_string_field( @@ -285,14 +306,12 @@ class CorrespondantCreationForm(FlaskForm): service = _build_string_field( "Service", required=False, render_kw={"class": "form-control"} ) - # depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) - - # def __init__(self, *args, **kwargs): - # super().__init__(*args, **kwargs) - - # self.depts.choices = [ - # (dept.id, dept.acronym) for dept in Departement.query.all() - # ] + origine = _build_string_field( + "Origine", required=False, render_kw={"class": "form-control"} + ) + notes = _build_string_field( + "Notes", required=False, render_kw={"class": "form-control"} + ) def validate(self): validate = True @@ -300,10 +319,9 @@ class CorrespondantCreationForm(FlaskForm): validate = False if not self.telephone.data and not self.mail.data: - self.telephone.errors.append( - "Saisir un moyen de contact (mail ou téléphone)" - ) - self.mail.errors.append("Saisir un moyen de contact (mail ou téléphone)") + msg = "Saisir un moyen de contact (mail ou téléphone)" + self.telephone.errors.append(msg) + self.mail.errors.append(msg) validate = False return validate @@ -321,7 +339,7 @@ class CorrespondantsCreationForm(FlaskForm): correspondant_list = [] for entry in self.correspondants.entries: - if entry.nom.data.strip() and entry.prenom.data.strip(): + if entry.nom.data and entry.prenom.data: if ( entry.nom.data.strip(), entry.prenom.data.strip(), @@ -351,6 +369,11 @@ class CorrespondantsCreationForm(FlaskForm): class CorrespondantModificationForm(FlaskForm): hidden_correspondant_id = HiddenField() hidden_entreprise_id = HiddenField() + civilite = SelectField( + "Civilité (*)", + choices=[("H", "Monsieur"), ("F", "Madame")], + validators=[DataRequired(message=CHAMP_REQUIS)], + ) nom = _build_string_field("Nom (*)") prenom = _build_string_field("Prénom (*)") telephone = _build_string_field("Téléphone (*)", required=False) @@ -360,16 +383,10 @@ class CorrespondantModificationForm(FlaskForm): ) poste = _build_string_field("Poste", required=False) service = _build_string_field("Service", required=False) - # depts = MultiCheckboxField("Départements", validators=[Optional()], coerce=int) + origine = _build_string_field("Origine", required=False) + notes = _build_string_field("Notes", required=False) 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): @@ -387,10 +404,9 @@ class CorrespondantModificationForm(FlaskForm): validate = False if not self.telephone.data and not self.mail.data: - self.telephone.errors.append( - "Saisir un moyen de contact (mail ou téléphone)" - ) - self.mail.errors.append("Saisir un moyen de contact (mail ou téléphone)") + msg = "Saisir un moyen de contact (mail ou téléphone)" + self.telephone.errors.append(msg) + self.mail.errors.append(msg) validate = False return validate @@ -593,6 +609,11 @@ class SuppressionConfirmationForm(FlaskForm): submit = SubmitField("Supprimer", render_kw=SUBMIT_MARGE) +class DesactivationConfirmationForm(FlaskForm): + notes_active = TextAreaField("Notes sur la désactivation", validators=[Optional()]) + submit = SubmitField("Désactiver", render_kw=SUBMIT_MARGE) + + class ValidationConfirmationForm(FlaskForm): submit = SubmitField("Valider", render_kw=SUBMIT_MARGE) diff --git a/app/entreprises/models.py b/app/entreprises/models.py index 90fcf335..4a318d24 100644 --- a/app/entreprises/models.py +++ b/app/entreprises/models.py @@ -9,14 +9,18 @@ class Entreprise(db.Model): adresse = db.Column(db.Text) codepostal = db.Column(db.Text) ville = db.Column(db.Text) - pays = db.Column(db.Text, default="FRANCE") + pays = db.Column(db.Text) visible = db.Column(db.Boolean, default=False) - correspondants = db.relationship( - "EntrepriseCorrespondant", + active = db.Column(db.Boolean, default=True) + notes_active = db.Column(db.Text) + + sites = db.relationship( + "EntrepriseSite", backref="entreprise", lazy="dynamic", cascade="all, delete-orphan", ) + offres = db.relationship( "EntrepriseOffre", backref="entreprise", @@ -35,13 +39,24 @@ class Entreprise(db.Model): } -# class EntrepriseSite(db.Model): -# __tablename__ = "are_sites" -# id = db.Column(db.Integer, primary_key=True) -# entreprise_id = db.Column( -# db.Integer, db.ForeignKey("are_entreprises.id", ondelete="cascade") -# ) -# nom = db.Column(db.Text) +class EntrepriseSite(db.Model): + __tablename__ = "are_sites" + id = db.Column(db.Integer, primary_key=True) + entreprise_id = db.Column( + db.Integer, db.ForeignKey("are_entreprises.id", ondelete="cascade") + ) + nom = db.Column(db.Text) + adresse = db.Column(db.Text) + codepostal = db.Column(db.Text) + ville = db.Column(db.Text) + pays = db.Column(db.Text) + + correspondants = db.relationship( + "EntrepriseCorrespondant", + backref="site", + lazy="dynamic", + cascade="all, delete-orphan", + ) class EntrepriseCorrespondant(db.Model): @@ -50,23 +65,29 @@ class EntrepriseCorrespondant(db.Model): entreprise_id = db.Column( db.Integer, db.ForeignKey("are_entreprises.id", ondelete="cascade") ) - # site_id = db.Column(db.Integer, db.ForeignKey("are_sites.id", ondelete="cascade")) + site_id = db.Column(db.Integer, db.ForeignKey("are_sites.id", ondelete="cascade")) + civilite = db.Column(db.String(1)) nom = db.Column(db.Text) prenom = db.Column(db.Text) telephone = db.Column(db.Text) mail = db.Column(db.Text) poste = db.Column(db.Text) service = db.Column(db.Text) + origine = db.Column(db.Text) + notes = db.Column(db.Text) def to_dict(self): entreprise = Entreprise.query.filter_by(id=self.entreprise_id).first() return { + "civilite": self.civilite, "nom": self.nom, "prenom": self.prenom, "telephone": self.telephone, "mail": self.mail, "poste": self.poste, "service": self.service, + "origine": self.origine, + "notes": self.notes, "entreprise_siret": entreprise.siret, } @@ -161,15 +182,6 @@ class EntrepriseOffreDepartement(db.Model): dept_id = db.Column(db.Integer, db.ForeignKey("departement.id", ondelete="cascade")) -# class EntrepriseCorrespondantDepartement(db.Model): -# __tablename__ = "are_correspondant_departement" -# id = db.Column(db.Integer, primary_key=True) -# 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")) - - 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 7fe2e727..b815b229 100644 --- a/app/entreprises/routes.py +++ b/app/entreprises/routes.py @@ -13,8 +13,10 @@ from app.decorators import permission_required from app.entreprises import LOGS_LEN from app.entreprises.forms import ( CorrespondantsCreationForm, + DesactivationConfirmationForm, EntrepriseCreationForm, EntrepriseModificationForm, + SiteCreationForm, SuppressionConfirmationForm, OffreCreationForm, OffreModificationForm, @@ -36,6 +38,7 @@ from app.entreprises.models import ( EntrepriseCorrespondant, EntrepriseLog, EntrepriseContact, + EntrepriseSite, EntrepriseStageApprentissage, EntrepriseEnvoiOffre, EntrepriseOffreDepartement, @@ -59,7 +62,7 @@ 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) + entreprises = Entreprise.query.filter_by(visible=True, active=True) logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all() return render_template( "entreprises/entreprises.html", @@ -101,7 +104,7 @@ def validation(): @bp.route("/correspondants", methods=["GET"]) -@permission_required(Permission.RelationsEntreprisesView) +@permission_required(Permission.RelationsEntreprisesCorrespondants) def correspondants(): """ Permet d'afficher une page avec la liste des correspondants des entreprises visibles et une liste des dernières opérations @@ -109,7 +112,7 @@ def correspondants(): correspondants = ( db.session.query(EntrepriseCorrespondant, Entreprise) .join(Entreprise, EntrepriseCorrespondant.entreprise_id == Entreprise.id) - .filter_by(visible=True) + .filter_by(visible=True, active=True) ) logs = EntrepriseLog.query.order_by(EntrepriseLog.date.desc()).limit(LOGS_LEN).all() return render_template( @@ -129,9 +132,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).first_or_404( - description=f"fiche entreprise {id} inconnue" - ) + entreprise = Entreprise.query.filter_by( + id=id, visible=True, active=True + ).first_or_404(description=f"fiche entreprise {id} inconnue") offres_with_files = [] depts = are.get_depts() for offre in entreprise.offres: @@ -145,7 +148,7 @@ 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) - correspondants = entreprise.correspondants[:] + sites = entreprise.sites[:] logs = ( EntrepriseLog.query.order_by(EntrepriseLog.date.desc()) .filter_by(object=id) @@ -163,7 +166,7 @@ def fiche_entreprise(id): "entreprises/fiche_entreprise.html", title="Fiche entreprise", entreprise=entreprise, - correspondants=correspondants, + sites=sites, offres=offres_with_files, logs=logs, stages_apprentissages=stages_apprentissages, @@ -294,16 +297,31 @@ def add_entreprise(): ) db.session.add(entreprise) db.session.commit() + db.session.refresh(entreprise) + site = EntrepriseSite( + entreprise_id=entreprise.id, + nom=form.nom_entreprise.data.strip(), + adresse=form.adresse.data.strip(), + codepostal=form.codepostal.data.strip(), + ville=form.ville.data.strip(), + pays=form.pays.data.strip() if form.pays.data.strip() else "FRANCE", + ) + db.session.add(site) + db.session.commit() if form.nom_correspondant.data.strip(): - db.session.refresh(entreprise) + db.session.refresh(site) correspondant = EntrepriseCorrespondant( entreprise_id=entreprise.id, + site_id=site.id, + civilite=form.civilite.data, 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(), + origine=form.origine.data.strip(), + notes=form.notes.data.strip(), ) db.session.add(correspondant) if current_user.has_permission(Permission.RelationsEntreprisesValidate, None): @@ -404,39 +422,27 @@ def edit_entreprise(id): ) -@bp.route("/fiche_entreprise/delete_entreprise/", methods=["GET", "POST"]) +@bp.route("/fiche_entreprise/desactiver/", methods=["GET", "POST"]) @permission_required(Permission.RelationsEntreprisesChange) -def delete_entreprise(id): +def fiche_entreprise_desactiver(id): """ - Permet de supprimer une entreprise de la base avec un formulaire de confirmation + Permet de désactiver une entreprise """ entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( description=f"entreprise {id} inconnue" ) - form = SuppressionConfirmationForm() + form = DesactivationConfirmationForm() if form.validate_on_submit(): - db.session.delete(entreprise) - # supprime les fichiers attachés aux offres - path = os.path.join( - Config.SCODOC_VAR_DIR, - "entreprises", - f"{entreprise.id}", - ) - if os.path.isdir(path): - shutil.rmtree(path) - log = EntrepriseLog( - authenticated_user=current_user.user_name, - object=entreprise.id, - text=f"Suppression de la fiche entreprise ({entreprise.nom})", - ) - db.session.add(log) + entreprise.notes_active = form.notes_active.data.strip() + entreprise.active = False db.session.commit() - flash("L'entreprise a été supprimé de la liste.") + flash("L'entreprise a été désactivé.") return redirect(url_for("entreprises.index")) return render_template( - "entreprises/delete_confirmation.html", - title="Supression entreprise", + "entreprises/confirmation_form.html", + title="Désactiver entreprise", form=form, + info_message="Cliquez sur le bouton Désactiver pour confirmer la désactivation", ) @@ -489,9 +495,10 @@ def delete_validation_entreprise(id): flash("L'entreprise a été supprimé de la liste des entreprise à valider.") return redirect(url_for("entreprises.validation")) return render_template( - "entreprises/delete_confirmation.html", + "entreprises/confirmation_form.html", title="Supression entreprise", form=form, + info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression", ) @@ -645,9 +652,10 @@ def delete_offre(id): flash("L'offre a été supprimé de la fiche entreprise.") return redirect(url_for("entreprises.fiche_entreprise", id=entreprise_id)) return render_template( - "entreprises/delete_confirmation.html", + "entreprises/confirmation_form.html", title="Supression offre", form=form, + info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression", ) @@ -683,26 +691,66 @@ def expired(id): return redirect(url_for("entreprises.fiche_entreprise", id=offre.entreprise_id)) -@bp.route("/fiche_entreprise//add_correspondant", methods=["GET", "POST"]) +@bp.route( + "/fiche_entreprise//add_site", + methods=["GET", "POST"], +) @permission_required(Permission.RelationsEntreprisesChange) -def add_correspondant(id): +def add_site(id): + entreprise = Entreprise.query.filter_by(id=id, visible=True).first_or_404( + description=f"entreprise {id} inconnue" + ) + form = SiteCreationForm() + if form.validate_on_submit(): + site = EntrepriseSite( + entreprise_id=entreprise.id, + nom=form.nom.data.strip(), + adresse=form.adresse.data.strip(), + codepostal=form.codepostal.data.strip(), + ville=form.ville.data.strip(), + pays=form.pays.data.strip() if form.pays.data.strip() else "FRANCE", + ) + db.session.add(site) + db.session.commit() + flash("Le site a été créé et ajouté à la fiche entreprise") + return redirect(url_for("entreprises.fiche_entreprise", id=entreprise.id)) + return render_template( + "entreprises/form.html", + title="Ajout site", + form=form, + ) + + +@bp.route( + "/fiche_entreprise//add_correspondant/", + methods=["GET", "POST"], +) +@permission_required(Permission.RelationsEntreprisesChange) +def add_correspondant(id_entreprise, id_site): """ 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" + 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).first_or_404( + description=f"site {id_site} inconnue" ) form = CorrespondantsCreationForm(hidden_entreprise_id=entreprise.id) if form.validate_on_submit(): for correspondant_entry in form.correspondants.entries: correspondant = EntrepriseCorrespondant( entreprise_id=entreprise.id, + site_id=site.id, + civilite=correspondant_entry.civilite.data, nom=correspondant_entry.nom.data.strip(), prenom=correspondant_entry.prenom.data.strip(), telephone=correspondant_entry.telephone.data.strip(), mail=correspondant_entry.mail.data.strip(), poste=correspondant_entry.poste.data.strip(), service=correspondant_entry.service.data.strip(), + origine=correspondant_entry.origine.data.strip(), + notes=correspondant_entry.notes.data.strip(), ) log = EntrepriseLog( authenticated_user=current_user.user_name, @@ -735,12 +783,15 @@ def edit_correspondant(id): hidden_correspondant_id=correspondant.id, ) if form.validate_on_submit(): + correspondant.civilite = form.civilite.data 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() + correspondant.origine = form.origine.data.strip() + correspondant.notes = form.notes.data.strip() log = EntrepriseLog( authenticated_user=current_user.user_name, object=correspondant.entreprise_id, @@ -750,15 +801,18 @@ def edit_correspondant(id): db.session.commit() flash("Le correspondant a été modifié.") return redirect( - url_for("entreprises.fiche_entreprise", id=correspondant.entreprise.id) + url_for("entreprises.fiche_entreprise", id=correspondant.entreprise_id) ) elif request.method == "GET": + form.civilite.data = correspondant.civilite 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 + form.origine.data = correspondant.origine + form.notes.data = correspondant.notes return render_template( "entreprises/form.html", title="Modification correspondant", @@ -790,9 +844,10 @@ def delete_correspondant(id): url_for("entreprises.fiche_entreprise", id=correspondant.entreprise_id) ) return render_template( - "entreprises/delete_confirmation.html", + "entreprises/confirmation_form.html", title="Supression correspondant", form=form, + info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression", ) @@ -1016,9 +1071,10 @@ def delete_stage_apprentissage(id): ) ) return render_template( - "entreprises/delete_confirmation.html", + "entreprises/confirmation_form.html", title="Supression stage/apprentissage", form=form, + info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression", ) @@ -1243,12 +1299,15 @@ def export_correspondants(): ) if correspondants: keys = [ + "civilite", "nom", "prenom", "telephone", "mail", "poste", "service", + "origine", + "notes", "entreprise_siret", ] titles = keys[:] @@ -1272,12 +1331,15 @@ 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[:] @@ -1306,12 +1368,15 @@ def import_correspondants(): correspondant_list = [] ligne = 0 titles = [ + "civilite", "nom", "prenom", "telephone", "mail", "poste", "service", + "origine", + "notes", "entreprise_siret", ] if data[1][0] != titles: @@ -1326,29 +1391,32 @@ def import_correspondants(): if ( are.verif_correspondant_data(correspondant_data) and ( - correspondant_data[0].strip(), correspondant_data[1].strip(), - correspondant_data[6].strip(), + correspondant_data[2].strip(), + correspondant_data[9].strip(), ) not in correspondant_list ): correspondant_list.append( ( - correspondant_data[0].strip(), correspondant_data[1].strip(), - correspondant_data[6].strip(), + correspondant_data[2].strip(), + correspondant_data[9].strip(), ) ) entreprise = Entreprise.query.filter_by( - siret=correspondant_data[6].strip() + siret=correspondant_data[9].strip() ).first() correspondant = EntrepriseCorrespondant( - nom=correspondant_data[0].strip(), - prenom=correspondant_data[1].strip(), - telephone=correspondant_data[2].strip(), - mail=correspondant_data[3].strip(), - poste=correspondant_data[4].strip(), - service=correspondant_data[5].strip(), + 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) @@ -1480,9 +1548,10 @@ def delete_offre_file(offre_id, filedir): url_for("entreprises.fiche_entreprise", id=offre.entreprise_id) ) return render_template( - "entreprises/delete_confirmation.html", + "entreprises/confirmation_form.html", title="Suppression fichier d'une offre", form=form, + info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression", ) diff --git a/app/scodoc/sco_permissions.py b/app/scodoc/sco_permissions.py index c72b3ff5..b57374fb 100644 --- a/app/scodoc/sco_permissions.py +++ b/app/scodoc/sco_permissions.py @@ -47,6 +47,7 @@ _SCO_PERMISSIONS = ( ), (1 << 25, "RelationsEntreprisesSend", "Envoyer des offres"), (1 << 26, "RelationsEntreprisesValidate", "Valide les entreprises"), + (1 << 27, "RelationsEntreprisesCorrespondants", "Voir les correspondants"), ) diff --git a/app/scodoc/sco_roles_default.py b/app/scodoc/sco_roles_default.py index 9529b031..df0cd453 100644 --- a/app/scodoc/sco_roles_default.py +++ b/app/scodoc/sco_roles_default.py @@ -62,7 +62,11 @@ SCO_ROLES_DEFAULTS = { # ObservateurEntreprise est un observateur de l'application entreprise "ObservateurEntreprise": (p.RelationsEntreprisesView,), # UtilisateurEntreprise est un utilisateur de l'application entreprise (droit de modification) - "UtilisateurEntreprise": (p.RelationsEntreprisesView, p.RelationsEntreprisesChange), + "UtilisateurEntreprise": ( + p.RelationsEntreprisesView, + p.RelationsEntreprisesChange, + p.RelationsEntreprisesCorrespondants, + ), # AdminEntreprise est un admin de l'application entreprise (toutes les actions possibles de l'application) "AdminEntreprise": ( p.RelationsEntreprisesView, @@ -70,6 +74,7 @@ SCO_ROLES_DEFAULTS = { p.RelationsEntreprisesExport, p.RelationsEntreprisesSend, p.RelationsEntreprisesValidate, + p.RelationsEntreprisesCorrespondants, ), # Super Admin est un root: création/suppression de départements # _tous_ les droits diff --git a/app/static/css/entreprises.css b/app/static/css/entreprises.css index 1f4e5f23..0ede866c 100644 --- a/app/static/css/entreprises.css +++ b/app/static/css/entreprises.css @@ -40,6 +40,11 @@ *background-color: #151515; } +.btn-remove { + margin-top: 5px; + margin-bottom: 5px; +} + .fiche-entreprise .btn { margin-top: 5px; margin-bottom: 5px; @@ -54,23 +59,24 @@ margin-bottom: -5px; } -.entreprise, .correspondant, .offre { +.entreprise, .correspondant, .offre, .site{ border: solid 2px; border-radius: 10px; padding: 10px; margin-bottom: 10px; + margin-top: 10px; } -.correspondants-et-offres { +.sites-et-offres { display: flex; justify-content: space-between; } -.correspondants-et-offres > div { +.sites-et-offres > div { flex: 1 0 0; } -.correspondants-et-offres > div:nth-child(2) { +.sites-et-offres > div:nth-child(2) { margin-left: 20px; } diff --git a/app/templates/entreprises/_correspondant.html b/app/templates/entreprises/_correspondant.html index 0def6b89..d8c00846 100644 --- a/app/templates/entreprises/_correspondant.html +++ b/app/templates/entreprises/_correspondant.html @@ -1,6 +1,7 @@ {# -*- mode: jinja-html -*- #}
+ Civilité : {{ correspondant.civilite|get_civilité }}
Nom : {{ correspondant.nom }}
Prénom : {{ correspondant.prenom }}
{% if correspondant.telephone %} @@ -15,6 +16,12 @@ {% if correspondant.service %} Service : {{ correspondant.service }}
{% endif %} + {% if correspondant.origine %} + Origine : {{ correspondant.origine }}
+ {% endif %} + {% if correspondant.notes %} + Notes : {{ correspondant.notes }}
+ {% endif %}
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} diff --git a/app/templates/entreprises/_offre.html b/app/templates/entreprises/_offre.html index 56541178..c799b6f4 100644 --- a/app/templates/entreprises/_offre.html +++ b/app/templates/entreprises/_offre.html @@ -1,6 +1,6 @@ {# -*- mode: jinja-html -*- #}
-
+
Ajouté le {{ offre[0].date_ajout.strftime('%d/%m/%y') }} à {{ offre[0].date_ajout.strftime('%Hh%M') }}
Intitulé : {{ offre[0].intitule }}
Description : {{ offre[0].description }}
diff --git a/app/templates/entreprises/ajout_correspondants.html b/app/templates/entreprises/ajout_correspondants.html index f7d5e5b1..18070b7f 100644 --- a/app/templates/entreprises/ajout_correspondants.html +++ b/app/templates/entreprises/ajout_correspondants.html @@ -35,6 +35,14 @@
{% endblock %} \ No newline at end of file diff --git a/app/templates/entreprises/delete_confirmation.html b/app/templates/entreprises/confirmation_form.html similarity index 75% rename from app/templates/entreprises/delete_confirmation.html rename to app/templates/entreprises/confirmation_form.html index abd59c47..fb873788 100644 --- a/app/templates/entreprises/delete_confirmation.html +++ b/app/templates/entreprises/confirmation_form.html @@ -5,7 +5,7 @@ {% block app_content %}

{{ title }}


-
Cliquez sur le bouton Supprimer pour confirmer votre supression
+
{{ info_message }}

diff --git a/app/templates/entreprises/entreprises.html b/app/templates/entreprises/entreprises.html index d870e594..f6d08cec 100644 --- a/app/templates/entreprises/entreprises.html +++ b/app/templates/entreprises/entreprises.html @@ -67,7 +67,7 @@
diff --git a/app/templates/entreprises/envoi_offre_form.html b/app/templates/entreprises/envoi_offre_form.html index ca5ba131..6ead6477 100644 --- a/app/templates/entreprises/envoi_offre_form.html +++ b/app/templates/entreprises/envoi_offre_form.html @@ -36,6 +36,14 @@
{% endblock %} \ No newline at end of file diff --git a/app/templates/entreprises/fiche_entreprise.html b/app/templates/entreprises/fiche_entreprise.html index b8d4b123..327a3bf7 100644 --- a/app/templates/entreprises/fiche_entreprise.html +++ b/app/templates/entreprises/fiche_entreprise.html @@ -37,24 +37,38 @@
- {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
+ {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} Modifier - Supprimer + Désactiver + Ajouter site Ajouter offre - Ajouter correspondant {% endif %} Liste contacts Voir les offres expirées -
+
-
- {% if correspondants %} +
+ {% if sites %}
-

Correspondants

- {% for correspondant in correspondants %} - {% include 'entreprises/_correspondant.html' %} +

Sites

+ {% for site in sites %} +
+ Nom : {{ site.nom }}
+ Adresse : {{ site.adresse }}
+ Code postal : {{ site.codepostal }}
+ Ville : {{ site.ville }}
+ Pays : {{ site.pays }} + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} +
Ajouter correspondant + {% endif %} + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %} + {% for correspondant in site.correspondants %} + {% include 'entreprises/_correspondant.html' %} + {% endfor %} + {% endif %} +
{% endfor %}
{% endif %} @@ -63,7 +77,7 @@

Offres - Voir les offres expirées

{% for offre in offres %} - {% include 'entreprises/_offre.html' %} + {% include 'entreprises/_offre.html' %} {% endfor %}
{% endif %} @@ -71,20 +85,20 @@
- {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} - Ajouter stage ou apprentissage - {% endif %}

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

+ {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} + Ajouter stage ou apprentissage + {% endif %} - - - - - - - + + + + + + + {% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %} {% endif %} diff --git a/app/templates/entreprises/form.html b/app/templates/entreprises/form.html index fe51a97b..067f4a50 100644 --- a/app/templates/entreprises/form.html +++ b/app/templates/entreprises/form.html @@ -23,15 +23,15 @@
Date débutDate finDuréeTypeÉtudiantFormationNotesDate débutDate finDuréeTypeÉtudiantFormationNotesAction