From 2f7de56432b2f15ccea10084768f8c083ec747c4 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 27 Feb 2024 08:12:48 +0100 Subject: [PATCH] =?UTF-8?q?Appliquer=20les=20contraintes=20de=20ChorusPro?= =?UTF-8?q?=20au=20nom=20des=20pi=C3=A8ces=20jointes=20(#87500)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eo_facture/migrations/0023_piecejointe.py | 11 +++++++++- eo_gestion/eo_facture/models.py | 21 +++++++++++++++++-- tests/test_admin.py | 17 +++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/eo_gestion/eo_facture/migrations/0023_piecejointe.py b/eo_gestion/eo_facture/migrations/0023_piecejointe.py index 0613a53..ac6dada 100644 --- a/eo_gestion/eo_facture/migrations/0023_piecejointe.py +++ b/eo_gestion/eo_facture/migrations/0023_piecejointe.py @@ -1,5 +1,6 @@ # Generated by Django 3.2.23 on 2024-02-20 15:15 +import django.core.validators import django.db.models.deletion from django.db import migrations, models @@ -17,7 +18,15 @@ class Migration(migrations.Migration): 'id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), ), - ('nom', models.TextField(blank=True, verbose_name='Nom')), + ( + 'nom', + models.TextField( + blank=True, + max_length=50, + validators=[django.core.validators.RegexValidator('[0-9a-zA-Z_]+.[0-9a-zA-Z]{3}')], + verbose_name='Nom', + ), + ), ('fichier', models.FileField(upload_to='', verbose_name='Fichier')), ( 'facture', diff --git a/eo_gestion/eo_facture/models.py b/eo_gestion/eo_facture/models.py index e779787..1d32893 100644 --- a/eo_gestion/eo_facture/models.py +++ b/eo_gestion/eo_facture/models.py @@ -852,16 +852,33 @@ class Payment(models.Model): ordering = ('-ligne_banque_pop__date_valeur',) +CHORUS_PJ_EXTENSIONS = '.BMP, .GIF, .FAX, .ODT, .PPT, .TIFF, .XLS, .BZ2, .GZ, .JPEG, .P7S, .RTF, .TXT, .XML, .CSV, .GZIP, .JPG, .PDF, .SVG, .XHTML, .XLSX, .DOC, .HTM, .ODP, .PNG, .TGZ, .XLC, .ZIP, .DOCX, .HTML, .ODS, .PPS, .TIF, .XLM, .PPTX' + + class PieceJointe(models.Model): facture = models.ForeignKey( Facture, related_name='pieces_jointes', on_delete=models.CASCADE, verbose_name='Facture' ) - nom = models.TextField(blank=True, verbose_name='Nom') + nom = models.TextField( + blank=True, + verbose_name='Nom', + validators=[RegexValidator('[0-9a-zA-Z_]+.[0-9a-zA-Z]{3}')], + max_length=50, + ) fichier = models.FileField(verbose_name='Fichier') def clean(self): + # https://communaute.chorus-pro.gouv.fr/pieces-jointes-dans-chorus-pro-quelques-regles-a-respecter/?lang=en if not self.nom: - self.nom = os.path.basename(self.fichier.name) + basename = os.path.basename(self.fichier.name) + name, ext = os.path.splitext(basename) + self.nom = name[:46] + ext[:4] + name, ext = os.path.splitext(self.nom) + + if ext.upper() not in CHORUS_PJ_EXTENSIONS.split(', '): + raise ValidationError( + f'Le nom de la pièce jointe doit avoir une extension parmi {CHORUS_PJ_EXTENSIONS}' + ) class Meta: verbose_name = 'Pièce jointe' diff --git a/tests/test_admin.py b/tests/test_admin.py index d81858f..c3dea62 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -134,6 +134,23 @@ class TestLoggedIn: response = response.click('Ajouter une facture', index=0) response.form.set('proforma', False) + response.form.set('pieces_jointes-0-nom', 'x' * 50 + '.zip') + response.form.set('pieces_jointes-0-fichier', Upload('pj1.zip', MINIMAL_ZIP_FILE, 'application/zip')) + response.form.set('pieces_jointes-1-nom', 'pj2') + response.form.set('pieces_jointes-1-fichier', Upload('pj2.zip', MINIMAL_ZIP_FILE, 'application/zip')) + + response = response.form.submit('_continue', status=200) + + assert [ + [et.text() for et in e.find('li').items()] for e in response.pyquery('.errorlist').items() + ] == [ + ['Assurez-vous que cette valeur comporte au plus 50 caractères (actuellement 54).'], + [ + 'Le nom de la pièce jointe doit avoir une extension parmi .BMP, .GIF, .FAX, .ODT, .PPT, .TIFF, .XLS, .BZ2, .GZ, .JPEG, .P7S, .RTF, .TXT, .XML, .CSV, .GZIP, .JPG, .PDF, .SVG, .XHTML, .XLSX, .DOC, .HTM, .ODP, .PNG, .TGZ, .XLC, .ZIP, .DOCX, .HTML, .ODS, .PPS, .TIF, .XLM, .PPTX' + ], + ['Saisissez une valeur valide.'], + ] + response.form.set('pieces_jointes-0-nom', 'pj1.zip') response.form.set('pieces_jointes-0-fichier', Upload('pj1.zip', MINIMAL_ZIP_FILE, 'application/zip')) response.form.set('pieces_jointes-1-nom', 'pj2.zip')