fix: resolve VisibilityScope choices attribute error in project document upload
This commit is contained in:
parent
91d7e0b176
commit
1e7f8123de
5 changed files with 98 additions and 19 deletions
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -118,6 +118,9 @@ class VisibilityScope(models.TextChoices):
|
||||||
SCOPED = "scoped", _("Interne et externe (sur base des thématiques et contrats)")
|
SCOPED = "scoped", _("Interne et externe (sur base des thématiques et contrats)")
|
||||||
|
|
||||||
|
|
||||||
|
VisibilityScope.CHOICES = VisibilityScope.choices
|
||||||
|
|
||||||
|
|
||||||
class DocumentFolder(models.Model):
|
class DocumentFolder(models.Model):
|
||||||
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
|
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
|
||||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||||
|
|
|
||||||
|
|
@ -1209,7 +1209,7 @@ class DocumentVisibilityAndIndependenceTests(TestCase):
|
||||||
class ProjectDocumentsVisibilityTests(TestCase):
|
class ProjectDocumentsVisibilityTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
from common.models import UserConfig, Thematic, UserThematics
|
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 projects.models import Project, ProjectUserAccess, ProjectTeamAccess
|
||||||
from documents.models import (
|
from documents.models import (
|
||||||
DocumentAttachment,
|
DocumentAttachment,
|
||||||
|
|
@ -1220,7 +1220,7 @@ class ProjectDocumentsVisibilityTests(TestCase):
|
||||||
)
|
)
|
||||||
from django.contrib.contenttypes.models import ContentType
|
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
|
# Internal user
|
||||||
self.int_user = User.objects.create_user(username="intern_user", password="pwd")
|
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_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.ext_team_config = UserConfig.objects.create(user=self.ext_team_user, is_intern=False)
|
||||||
self.company = Company.objects.create(name="Contractor Corp")
|
self.company = Company.objects.create(name="Contractor Corp")
|
||||||
self.team = Team.objects.create(name="Project Team", company=self.company)
|
self.team = CompanyTeam.objects.create(name="Project Team", company=self.company)
|
||||||
CompanyMember.objects.create(user=self.ext_team_user, company=self.company, team=self.team)
|
member = CompanyMember.objects.create(name="ext_team_user", user=self.ext_team_user)
|
||||||
|
member.teams.add(self.team)
|
||||||
|
|
||||||
# External user 3 (no access)
|
# External user 3 (no access)
|
||||||
self.ext_no_access = User.objects.create_user(username="ext_no_access", password="pwd")
|
self.ext_no_access = User.objects.create_user(username="ext_no_access", password="pwd")
|
||||||
|
|
@ -1256,7 +1257,14 @@ class ProjectDocumentsVisibilityTests(TestCase):
|
||||||
# Grant team access to team
|
# Grant team access to team
|
||||||
ProjectTeamAccess.objects.create(project=self.project, team=self.team, can_view=True)
|
ProjectTeamAccess.objects.create(project=self.project, team=self.team, can_view=True)
|
||||||
|
|
||||||
# Create Project Folder (SCOPED)
|
# Project Folder (SCOPED)
|
||||||
|
project_ct = ContentType.objects.get_for_model(self.project)
|
||||||
|
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(
|
self.project_folder = DocumentFolder.objects.create(
|
||||||
name="P12345 Documents",
|
name="P12345 Documents",
|
||||||
slug="project-p12345-boulevard",
|
slug="project-p12345-boulevard",
|
||||||
|
|
@ -1264,7 +1272,6 @@ class ProjectDocumentsVisibilityTests(TestCase):
|
||||||
visibility=VisibilityScope.SCOPED,
|
visibility=VisibilityScope.SCOPED,
|
||||||
created_by=self.int_user,
|
created_by=self.int_user,
|
||||||
)
|
)
|
||||||
project_ct = ContentType.objects.get_for_model(self.project)
|
|
||||||
DocumentFolderAttachment.objects.create(
|
DocumentFolderAttachment.objects.create(
|
||||||
folder=self.project_folder,
|
folder=self.project_folder,
|
||||||
content_type=project_ct,
|
content_type=project_ct,
|
||||||
|
|
|
||||||
|
|
@ -206,5 +206,51 @@ class ProjectViewerPermissionsTest(TestCase):
|
||||||
self.assertNotIn(self.proj_roads_strict, viewable)
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,7 @@ def projects_add_document(request, project_id):
|
||||||
from documents.permissions import user_can_change_visibility
|
from documents.permissions import user_can_change_visibility
|
||||||
raw_visibility = request.POST.get(f'visibility_{i}', '').strip()
|
raw_visibility = request.POST.get(f'visibility_{i}', '').strip()
|
||||||
visibility = None
|
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):
|
if user_can_change_visibility(request.user):
|
||||||
visibility = raw_visibility
|
visibility = raw_visibility
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue