fix: resolve VisibilityScope choices attribute error in project document upload

This commit is contained in:
kdeterme 2026-09-09 22:59:09 +02:00
parent 91d7e0b176
commit 1e7f8123de
5 changed files with 98 additions and 19 deletions

View file

@ -0,0 +1,23 @@
# Generated by Django 6.0.7 on 2026-09-09 20:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('documents', '0003_documentfolder_visibility_manageddocument_thematics_and_more'),
]
operations = [
migrations.AlterField(
model_name='documentfolder',
name='visibility',
field=models.CharField(choices=[('private', 'Privé (Créateur uniquement)'), ('restricted', 'Partagé avec certains utilisateurs'), ('internal', 'Interne (sur base des thématiques et contrats)'), ('scoped', 'Interne et externe (sur base des thématiques et contrats)')], db_index=True, default='internal', max_length=20, verbose_name='Visibility'),
),
migrations.AlterField(
model_name='manageddocument',
name='visibility',
field=models.CharField(choices=[('private', 'Privé (Créateur uniquement)'), ('restricted', 'Partagé avec certains utilisateurs'), ('internal', 'Interne (sur base des thématiques et contrats)'), ('scoped', 'Interne et externe (sur base des thématiques et contrats)')], db_index=True, default='internal', max_length=20, verbose_name='Visibility'),
),
]

View file

@ -118,6 +118,9 @@ class VisibilityScope(models.TextChoices):
SCOPED = "scoped", _("Interne et externe (sur base des thématiques et contrats)")
VisibilityScope.CHOICES = VisibilityScope.choices
class DocumentFolder(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
name = models.CharField(max_length=255, verbose_name=_("Name"))

View file

@ -1209,7 +1209,7 @@ class DocumentVisibilityAndIndependenceTests(TestCase):
class ProjectDocumentsVisibilityTests(TestCase):
def setUp(self):
from common.models import UserConfig, Thematic, UserThematics
from contracts.models import Company, Team, CompanyMember
from contracts.models import Company, CompanyTeam, CompanyMember
from projects.models import Project, ProjectUserAccess, ProjectTeamAccess
from documents.models import (
DocumentAttachment,
@ -1220,7 +1220,7 @@ class ProjectDocumentsVisibilityTests(TestCase):
)
from django.contrib.contenttypes.models import ContentType
self.thematic = Thematic.objects.create(name="Voirie", code="VOI")
self.thematic = Thematic.objects.create(name_fr="Voirie", code="VOI")
# Internal user
self.int_user = User.objects.create_user(username="intern_user", password="pwd")
@ -1235,8 +1235,9 @@ class ProjectDocumentsVisibilityTests(TestCase):
self.ext_team_user = User.objects.create_user(username="ext_team_user", password="pwd")
self.ext_team_config = UserConfig.objects.create(user=self.ext_team_user, is_intern=False)
self.company = Company.objects.create(name="Contractor Corp")
self.team = Team.objects.create(name="Project Team", company=self.company)
CompanyMember.objects.create(user=self.ext_team_user, company=self.company, team=self.team)
self.team = CompanyTeam.objects.create(name="Project Team", company=self.company)
member = CompanyMember.objects.create(name="ext_team_user", user=self.ext_team_user)
member.teams.add(self.team)
# External user 3 (no access)
self.ext_no_access = User.objects.create_user(username="ext_no_access", password="pwd")
@ -1256,21 +1257,27 @@ class ProjectDocumentsVisibilityTests(TestCase):
# Grant team access to team
ProjectTeamAccess.objects.create(project=self.project, team=self.team, can_view=True)
# Create Project Folder (SCOPED)
self.project_folder = DocumentFolder.objects.create(
name="P12345 Documents",
slug="project-p12345-boulevard",
application_label="projects",
visibility=VisibilityScope.SCOPED,
created_by=self.int_user,
)
# Project Folder (SCOPED)
project_ct = ContentType.objects.get_for_model(self.project)
DocumentFolderAttachment.objects.create(
folder=self.project_folder,
content_type=project_ct,
object_id=self.project.pk,
is_default=True,
)
dfa = DocumentFolderAttachment.objects.filter(content_type=project_ct, object_id=self.project.pk, is_default=True).first()
if dfa:
self.project_folder = dfa.folder
self.project_folder.visibility = VisibilityScope.SCOPED
self.project_folder.save()
else:
self.project_folder = DocumentFolder.objects.create(
name="P12345 Documents",
slug="project-p12345-boulevard",
application_label="projects",
visibility=VisibilityScope.SCOPED,
created_by=self.int_user,
)
DocumentFolderAttachment.objects.create(
folder=self.project_folder,
content_type=project_ct,
object_id=self.project.pk,
is_default=True,
)
# Create Scoped Document
self.scoped_doc = ManagedDocument.objects.create(

View file

@ -206,5 +206,51 @@ class ProjectViewerPermissionsTest(TestCase):
self.assertNotIn(self.proj_roads_strict, viewable)
class ProjectAddDocumentTest(TestCase):
def setUp(self):
from common.models import Role
from projects.signals import ensure_project_document_folder
self.user = User.objects.create_user(username="projadmin", password="password123")
self.user_config = UserConfig.objects.create(user=self.user, is_intern=True)
admin_role, _ = Role.objects.get_or_create(name='admin')
self.user_config.roles.add(admin_role)
self.thematic = Thematic.objects.create(code="them_test", name_fr="Them Test", name_nl="Them Test")
self.project = Project.objects.create(
name="Test Project",
created_by=self.user,
status="in_progress"
)
self.project.thematics.add(self.thematic)
ensure_project_document_folder(self.project)
self.client = Client()
self.client.login(username="projadmin", password="password123")
def test_visibility_scope_choices_compatibility(self):
from documents.models import VisibilityScope
self.assertTrue(hasattr(VisibilityScope, 'CHOICES'))
self.assertEqual(dict(VisibilityScope.CHOICES), dict(VisibilityScope.choices))
def test_add_document_with_visibility(self):
from django.core.files.uploadedfile import SimpleUploadedFile
from documents.models import ManagedDocument, VisibilityScope
upload = SimpleUploadedFile("test_doc.pdf", b"%PDF-1.4 test content", content_type="application/pdf")
post_data = {
"files": [upload],
"file_count": "1",
"visibility_0": "internal",
}
url = reverse("projects:projects_add_document", kwargs={"project_id": self.project.id})
response = self.client.post(url, post_data, follow=True)
self.assertEqual(response.status_code, 200)
doc = ManagedDocument.objects.filter(title="test_doc").first()
self.assertIsNotNone(doc)
self.assertEqual(doc.visibility, VisibilityScope.INTERNAL)

View file

@ -595,7 +595,7 @@ def projects_add_document(request, project_id):
from documents.permissions import user_can_change_visibility
raw_visibility = request.POST.get(f'visibility_{i}', '').strip()
visibility = None
if raw_visibility and raw_visibility in dict(VisibilityScope.CHOICES):
if raw_visibility and raw_visibility in VisibilityScope.values:
if user_can_change_visibility(request.user):
visibility = raw_visibility
else: