feat(projects): add project-specific member rates
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from apps.clients.models import Client
|
||||
from apps.projects.models import Project, ProjectAccess
|
||||
from apps.projects.models import Project, ProjectAccess, ProjectUserRate
|
||||
from apps.users.models import User
|
||||
from apps.workspaces.models import Workspace, WorkspaceMembership
|
||||
from apps.workspaces.models import PriceUnit, Workspace, WorkspaceMembership, WorkspaceUserRate
|
||||
|
||||
|
||||
class ProjectViewTests(APITestCase):
|
||||
@@ -15,6 +17,7 @@ class ProjectViewTests(APITestCase):
|
||||
first_name="Owner",
|
||||
)
|
||||
cls.workspace = Workspace.objects.create(name="Projects", owner=cls.owner)
|
||||
PriceUnit.objects.create(code="USD", name="US Dollar", local_name="Dollar", symbol="$")
|
||||
cls.member = User.objects.create_user(
|
||||
mobile="09121110002",
|
||||
password="secret123",
|
||||
@@ -47,6 +50,14 @@ class ProjectViewTests(APITestCase):
|
||||
cls.first_project = Project.objects.get(name="Alpha")
|
||||
ProjectAccess.objects.create(project=cls.first_project, user=cls.member)
|
||||
ProjectAccess.objects.create(project=cls.second_project, user=cls.member)
|
||||
WorkspaceUserRate.objects.create(
|
||||
workspace=cls.workspace,
|
||||
user=cls.member,
|
||||
hourly_rate=Decimal("25.00"),
|
||||
currency="USD",
|
||||
effective_from=cls.workspace.created_at,
|
||||
is_active=True,
|
||||
)
|
||||
|
||||
def test_project_list_supports_multi_client_filter(self):
|
||||
self.client.force_authenticate(user=self.member)
|
||||
@@ -84,6 +95,9 @@ class ProjectViewTests(APITestCase):
|
||||
items = access_response.data["items"]
|
||||
gamma_item = next(item for item in items if item["id"] == str(self.third_project.id))
|
||||
self.assertFalse(gamma_item["has_access"])
|
||||
alpha_item = next(item for item in items if item["id"] == str(self.first_project.id))
|
||||
self.assertEqual(alpha_item["workspace_rate"]["hourly_rate"], "25.00")
|
||||
self.assertIsNone(alpha_item["project_rate"])
|
||||
|
||||
grant_response = self.client.post(
|
||||
"/api/projects/access/grant/",
|
||||
@@ -114,3 +128,66 @@ class ProjectViewTests(APITestCase):
|
||||
)
|
||||
self.assertEqual(revoke_response.status_code, 200)
|
||||
self.assertFalse(ProjectAccess.objects.filter(project=self.first_project, user=self.member).exists())
|
||||
|
||||
def test_project_access_rate_endpoint_saves_override_and_keeps_it_dormant_after_revoke(self):
|
||||
self.client.force_authenticate(user=self.owner)
|
||||
|
||||
save_response = self.client.post(
|
||||
"/api/projects/access/rate/",
|
||||
{
|
||||
"workspace": str(self.workspace.id),
|
||||
"user": str(self.member.id),
|
||||
"project": str(self.first_project.id),
|
||||
"hourly_rate": "44.50",
|
||||
"currency": "USD",
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(save_response.status_code, 200)
|
||||
self.assertFalse(save_response.data["removed"])
|
||||
self.assertEqual(save_response.data["item"]["project_rate"]["hourly_rate"], "44.50")
|
||||
self.assertTrue(
|
||||
ProjectUserRate.objects.filter(project=self.first_project, user=self.member, is_deleted=False).exists()
|
||||
)
|
||||
|
||||
revoke_response = self.client.post(
|
||||
"/api/projects/access/revoke/",
|
||||
{
|
||||
"workspace": str(self.workspace.id),
|
||||
"user": str(self.member.id),
|
||||
"project_ids": [str(self.first_project.id)],
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(revoke_response.status_code, 200)
|
||||
self.assertTrue(
|
||||
ProjectUserRate.objects.filter(project=self.first_project, user=self.member, is_deleted=False).exists()
|
||||
)
|
||||
|
||||
access_response = self.client.get(
|
||||
"/api/projects/access/",
|
||||
{"workspace": str(self.workspace.id), "user": str(self.member.id)},
|
||||
)
|
||||
self.assertEqual(access_response.status_code, 200)
|
||||
alpha_item = next(item for item in access_response.data["items"] if item["id"] == str(self.first_project.id))
|
||||
self.assertFalse(alpha_item["has_access"])
|
||||
self.assertEqual(alpha_item["project_rate"]["hourly_rate"], "44.50")
|
||||
|
||||
def test_project_access_rate_endpoint_rejects_projects_without_access(self):
|
||||
self.client.force_authenticate(user=self.owner)
|
||||
|
||||
response = self.client.post(
|
||||
"/api/projects/access/rate/",
|
||||
{
|
||||
"workspace": str(self.workspace.id),
|
||||
"user": str(self.member.id),
|
||||
"project": str(self.third_project.id),
|
||||
"hourly_rate": "44.50",
|
||||
"currency": "USD",
|
||||
},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertIn("Grant project access", response.data["detail"])
|
||||
|
||||
Reference in New Issue
Block a user