feat(workspaces): add current user rates endpoint
This commit is contained in:
@@ -3,7 +3,8 @@ from django.shortcuts import get_object_or_404
|
||||
from rest_framework import status
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.decorators import action
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
@@ -15,6 +16,8 @@ from apps.notifications.services import (
|
||||
notify_workspace_membership_removed,
|
||||
notify_workspace_membership_role_changed,
|
||||
)
|
||||
from apps.projects.models import ProjectUserRate
|
||||
from apps.projects.services.access import filter_projects_for_user
|
||||
from apps.workspaces.api.permissions import (
|
||||
CanWorkspaceManageMembers,
|
||||
IsWorkspaceAdmin,
|
||||
@@ -78,6 +81,8 @@ class WorkspaceViewSet(ModelViewSet):
|
||||
def get_permissions(self):
|
||||
if self.action in ["list", "retrieve"]:
|
||||
return [IsAuthenticated(), IsWorkspaceMember()]
|
||||
if self.action == "my_rates":
|
||||
return [IsAuthenticated()]
|
||||
if self.action in ["update", "partial_update"]:
|
||||
return [IsAuthenticated(), IsWorkspaceAdmin()]
|
||||
|
||||
@@ -86,8 +91,86 @@ class WorkspaceViewSet(ModelViewSet):
|
||||
|
||||
return [IsAuthenticated()]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(owner=self.request.user)
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(owner=self.request.user)
|
||||
|
||||
@action(detail=True, methods=["get"], url_path="my-rates")
|
||||
def my_rates(self, request, pk=None):
|
||||
workspace = self.get_object()
|
||||
if not has_workspace_capability(request.user, workspace, WORKSPACE_VIEW):
|
||||
raise PermissionDenied("You do not have access to this workspace.")
|
||||
|
||||
def serialize_rate(rate):
|
||||
if not rate:
|
||||
return None
|
||||
unit = PriceUnit.objects.filter(code=rate.currency, is_deleted=False).first()
|
||||
return {
|
||||
"id": str(rate.id),
|
||||
"hourly_rate": str(rate.hourly_rate),
|
||||
"currency": rate.currency,
|
||||
"price_unit": PriceUnitSerializer(unit).data if unit else None,
|
||||
"effective_from": rate.effective_from.isoformat() if rate.effective_from else None,
|
||||
}
|
||||
|
||||
workspace_rate = (
|
||||
WorkspaceUserRate.objects.filter(
|
||||
workspace=workspace,
|
||||
user=request.user,
|
||||
is_deleted=False,
|
||||
)
|
||||
.order_by("-effective_from", "-updated_at")
|
||||
.first()
|
||||
)
|
||||
accessible_projects = list(
|
||||
filter_projects_for_user(
|
||||
request.user,
|
||||
workspace.projects.filter(is_deleted=False).select_related("client"),
|
||||
).order_by("client__name", "name")
|
||||
)
|
||||
accessible_project_ids = [project.id for project in accessible_projects]
|
||||
project_rates_by_project_id = {}
|
||||
for rate in (
|
||||
ProjectUserRate.objects.filter(
|
||||
project_id__in=accessible_project_ids,
|
||||
user=request.user,
|
||||
is_active=True,
|
||||
is_deleted=False,
|
||||
)
|
||||
.select_related("project", "project__client")
|
||||
.order_by("project_id", "-effective_from", "-updated_at")
|
||||
):
|
||||
project_rates_by_project_id.setdefault(str(rate.project_id), rate)
|
||||
|
||||
payload = {
|
||||
"workspace": {
|
||||
"id": str(workspace.id),
|
||||
"name": workspace.name,
|
||||
},
|
||||
"workspace_rate": serialize_rate(workspace_rate),
|
||||
"accessible_project_count": len(accessible_projects),
|
||||
"project_rates": [
|
||||
{
|
||||
"project": {
|
||||
"id": str(project.id),
|
||||
"name": project.name,
|
||||
"client": (
|
||||
{"id": str(project.client_id), "name": project.client.name}
|
||||
if project.client_id and project.client
|
||||
else None
|
||||
),
|
||||
},
|
||||
"rate": serialize_rate(project_rates_by_project_id[str(project.id)]),
|
||||
}
|
||||
for project in accessible_projects
|
||||
if str(project.id) in project_rates_by_project_id
|
||||
],
|
||||
}
|
||||
payload["project_override_count"] = len(payload["project_rates"])
|
||||
payload["workspace_fallback_project_count"] = max(
|
||||
payload["accessible_project_count"] - payload["project_override_count"],
|
||||
0,
|
||||
)
|
||||
return Response(payload)
|
||||
|
||||
|
||||
class WorkspaceMembershipViewSet(ModelViewSet):
|
||||
|
||||
Reference in New Issue
Block a user