133 lines
4.2 KiB
Python
133 lines
4.2 KiB
Python
from decimal import Decimal
|
|
|
|
import pytest
|
|
from rest_framework.test import APIClient
|
|
|
|
from apps.projects.models import Project, ProjectMembership
|
|
from apps.time_entries.services.rates import resolve_rate
|
|
from apps.users.models import User
|
|
from apps.workspaces.models import PriceUnit, Workspace, WorkspaceMembership, WorkspaceUserRate
|
|
|
|
|
|
@pytest.fixture()
|
|
def api_client():
|
|
return APIClient()
|
|
|
|
|
|
@pytest.fixture()
|
|
def owner(db):
|
|
return User.objects.create_user(mobile="09127770001", password="secret123")
|
|
|
|
|
|
@pytest.fixture()
|
|
def admin(db):
|
|
return User.objects.create_user(mobile="09127770002", password="secret123")
|
|
|
|
|
|
@pytest.fixture()
|
|
def member(db):
|
|
return User.objects.create_user(mobile="09127770003", password="secret123")
|
|
|
|
|
|
@pytest.fixture()
|
|
def workspace(owner, admin, member):
|
|
workspace = Workspace.objects.create(name="Rates", owner=owner)
|
|
WorkspaceMembership.objects.create(workspace=workspace, user=admin, role=WorkspaceMembership.Role.ADMIN, is_active=True)
|
|
WorkspaceMembership.objects.create(workspace=workspace, user=member, role=WorkspaceMembership.Role.MEMBER, is_active=True)
|
|
return workspace
|
|
|
|
|
|
@pytest.fixture()
|
|
def project(workspace, owner, admin, member):
|
|
project = Project.objects.create(workspace=workspace, name="Billing")
|
|
ProjectMembership.objects.create(project=project, user=owner, role=ProjectMembership.Role.MANAGER, is_active=True)
|
|
ProjectMembership.objects.create(project=project, user=admin, role=ProjectMembership.Role.MANAGER, is_active=True)
|
|
ProjectMembership.objects.create(project=project, user=member, role=ProjectMembership.Role.MEMBER, is_active=True)
|
|
return project
|
|
|
|
|
|
@pytest.fixture()
|
|
def price_units(db):
|
|
PriceUnit.objects.create(code="USD", name="US Dollar", local_name="دلار آمریکا", symbol="$")
|
|
PriceUnit.objects.create(code="EUR", name="Euro", local_name="یورو", symbol="€")
|
|
|
|
|
|
def test_resolve_rate_uses_workspace_user_rate(workspace, project, member):
|
|
WorkspaceUserRate.objects.create(
|
|
workspace=workspace,
|
|
user=member,
|
|
hourly_rate=Decimal("40.00"),
|
|
currency="EUR",
|
|
effective_from=project.created_at,
|
|
is_active=True,
|
|
)
|
|
|
|
hourly_rate, currency = resolve_rate(member, project)
|
|
|
|
assert hourly_rate == Decimal("40.00")
|
|
assert currency == "EUR"
|
|
|
|
|
|
def test_resolve_rate_falls_back_to_workspace_user_rate(workspace, project, member):
|
|
WorkspaceUserRate.objects.create(
|
|
workspace=workspace,
|
|
user=member,
|
|
hourly_rate=Decimal("40.00"),
|
|
currency="EUR",
|
|
effective_from=project.created_at,
|
|
is_active=True,
|
|
)
|
|
|
|
hourly_rate, currency = resolve_rate(member, project)
|
|
|
|
assert hourly_rate == Decimal("40.00")
|
|
assert currency == "EUR"
|
|
|
|
|
|
def test_admin_can_manage_workspace_user_rates(api_client, admin, member, workspace, price_units):
|
|
api_client.force_authenticate(user=admin)
|
|
|
|
create_response = api_client.post(
|
|
"/api/workspace-user-rates/",
|
|
{
|
|
"workspace_id": str(workspace.id),
|
|
"user_id": str(member.id),
|
|
"hourly_rate": "35.50",
|
|
"currency": "USD",
|
|
},
|
|
format="json",
|
|
)
|
|
|
|
assert create_response.status_code == 201
|
|
rate_id = create_response.data["id"]
|
|
assert WorkspaceUserRate.objects.filter(id=rate_id, is_deleted=False).exists()
|
|
|
|
update_response = api_client.patch(
|
|
f"/api/workspace-user-rates/{rate_id}/",
|
|
{"hourly_rate": "42.00"},
|
|
format="json",
|
|
)
|
|
assert update_response.status_code == 200
|
|
assert update_response.data["hourly_rate"] == "42.00"
|
|
|
|
delete_response = api_client.delete(f"/api/workspace-user-rates/{rate_id}/")
|
|
assert delete_response.status_code == 204
|
|
assert WorkspaceUserRate.all_objects.get(id=rate_id).is_deleted is True
|
|
|
|
|
|
def test_member_cannot_manage_rates(api_client, member, workspace, price_units):
|
|
api_client.force_authenticate(user=member)
|
|
|
|
workspace_response = api_client.post(
|
|
"/api/workspace-user-rates/",
|
|
{
|
|
"workspace_id": str(workspace.id),
|
|
"user_id": str(member.id),
|
|
"hourly_rate": "25.00",
|
|
"currency": "USD",
|
|
},
|
|
format="json",
|
|
)
|
|
|
|
assert workspace_response.status_code == 403
|