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')