From 8de652c57b7304494a4a82216ae95a0e3e5207c0 Mon Sep 17 00:00:00 2001 From: Fazliddin Abdurahimov Date: Tue, 5 Aug 2025 16:54:21 +0500 Subject: [PATCH] TODO: fix create contract related endpoints --- core/apps/companies/models/folders.py | 2 +- core/apps/companies/permissions/folders.py | 26 ++++++++---- .../serializers/folders/company_folders.py | 11 +++-- core/apps/companies/views/folders.py | 41 ++++++++++++++++--- .../serializers/contracts/contracts.py | 6 ++- core/apps/contracts/views/contracts.py | 13 +++++- 6 files changed, 76 insertions(+), 23 deletions(-) diff --git a/core/apps/companies/models/folders.py b/core/apps/companies/models/folders.py index e4012f5..11921e0 100644 --- a/core/apps/companies/models/folders.py +++ b/core/apps/companies/models/folders.py @@ -36,7 +36,7 @@ class CompanyFolderModel(UUIDPrimaryKeyBaseModel): contracts = models.ManyToManyField( # type: ignore ContractModel, verbose_name=_("Contracts"), - related_name="folders", + related_name="folders", null=True, blank=True ) diff --git a/core/apps/companies/permissions/folders.py b/core/apps/companies/permissions/folders.py index baa6e97..e4ac27b 100644 --- a/core/apps/companies/permissions/folders.py +++ b/core/apps/companies/permissions/folders.py @@ -1,12 +1,20 @@ -from rest_framework import permissions +from rest_framework import permissions # type: ignore +from rest_framework.request import HttpRequest # type: ignore +from rest_framework.views import APIView # type: ignore +from core.apps.companies.models import CompanyFolderModel -class CompanyfolderPermission(permissions.BasePermission): +class IsFolderOwner(permissions.IsAuthenticated): - def __init__(self) -> None: ... - - def __call__(self, *args, **kwargs): - return self - - def has_permission(self, request, view): - return True + def has_object_permission( # type: ignore + self, + request: HttpRequest, + view: APIView, + obj: CompanyFolderModel + ) -> bool: + return CompanyFolderModel.objects.filter( + company__accounts__user=request.user, + id=obj.id + ).exists() + + \ No newline at end of file diff --git a/core/apps/companies/serializers/folders/company_folders.py b/core/apps/companies/serializers/folders/company_folders.py index 9a290f0..1b13f5e 100644 --- a/core/apps/companies/serializers/folders/company_folders.py +++ b/core/apps/companies/serializers/folders/company_folders.py @@ -22,10 +22,6 @@ class RetrieveCompanyFolderSerializer(BaseCompanyFolderSerializer): class Meta(BaseCompanyFolderSerializer.Meta): ... -class CreateCompanyFolderSerializer(BaseCompanyFolderSerializer): - class Meta(BaseCompanyFolderSerializer.Meta): ... - - class UpdateCompanyFolderSerializer(BaseCompanyFolderSerializer): class Meta(BaseCompanyFolderSerializer.Meta): ... @@ -35,6 +31,13 @@ class DestroyCompanyFolderSerializer(BaseCompanyFolderSerializer): fields = ["id"] +########################################################### +# Create Serializers +########################################################### +class CreateCompanyFolderSerializer(BaseCompanyFolderSerializer): + class Meta(BaseCompanyFolderSerializer.Meta): ... + + class CreateCompanyFolderFromCompanySerializer(CreateCompanyFolderSerializer): class Meta(CreateCompanyFolderSerializer.Meta): read_only_fields = ( diff --git a/core/apps/companies/views/folders.py b/core/apps/companies/views/folders.py index 69abd84..975ecfb 100644 --- a/core/apps/companies/views/folders.py +++ b/core/apps/companies/views/folders.py @@ -1,8 +1,16 @@ -from django_core.mixins import BaseViewSetMixin -from drf_spectacular.utils import extend_schema -from rest_framework.permissions import AllowAny, IsAdminUser -from rest_framework.viewsets import ModelViewSet +from typing import cast +from django_core.mixins import BaseViewSetMixin # type: ignore +from drf_spectacular.utils import extend_schema +from rest_framework.decorators import action # type: ignore +from rest_framework.permissions import AllowAny, IsAdminUser # type: ignore +from rest_framework.viewsets import ModelViewSet # type: ignore +from rest_framework.request import HttpRequest # type: ignore +from rest_framework.response import Response # type: ignore +from rest_framework import status # type: ignore + +from core.apps.contracts.serializers.contracts import CreateContractSerializer +from core.apps.companies.permissions.folders import IsFolderOwner from core.apps.companies.models import CompanyFolderModel from core.apps.companies.serializers.folders import ( CreateCompanyFolderSerializer, @@ -19,17 +27,38 @@ class CompanyFolderView(BaseViewSetMixin, ModelViewSet): serializer_class = ListCompanyFolderSerializer permission_classes = [AllowAny] - action_permission_classes = { + action_permission_classes = { # type: ignore "list": [IsAdminUser], "retrieve": [IsAdminUser], "create": [IsAdminUser], "update": [IsAdminUser], "destroy": [IsAdminUser], + "create_contract": [IsFolderOwner] } - action_serializer_class = { + action_serializer_class = { # type: ignore "list": ListCompanyFolderSerializer, "retrieve": RetrieveCompanyFolderSerializer, "create": CreateCompanyFolderSerializer, "update": UpdateCompanyFolderSerializer, "destroy": DestroyCompanyFolderSerializer, + "create_contract": CreateContractSerializer, } + + @extend_schema( + summary="Create Contract For Folder", + description="Create Contract For Folder", + ) + @action(methods=["POST"], detail=True, url_path="contracts") + def create_contract( + self, + request: HttpRequest, + *args: object, + **kwargs: object + ) -> Response: + ser = cast( + CreateContractSerializer, + self.get_serializer(data=request.data) # type: ignore + ) + ser.is_valid(raise_exception=True) + ser.save() + return Response(ser.data, status.HTTP_201_CREATED) diff --git a/core/apps/contracts/serializers/contracts/contracts.py b/core/apps/contracts/serializers/contracts/contracts.py index ab1626a..876059f 100644 --- a/core/apps/contracts/serializers/contracts/contracts.py +++ b/core/apps/contracts/serializers/contracts/contracts.py @@ -93,7 +93,11 @@ class CreateOwnersForContractSerializer(CreateContractOwnerSerializer): class CreateContractAttachedFileForContractSerializer(CreateContractAttachedFileSerializer): - class Meta(CreateContractAttachedFileSerializer.Meta): ... + class Meta(CreateContractAttachedFileSerializer.Meta): + read_only_fields = ( + "contract", + *CreateContractAttachedFileSerializer.Meta.read_only_fields + ) def create(self, validated_data: dict[str, object]) -> Meta.model: contract = self.context.get("contract") diff --git a/core/apps/contracts/views/contracts.py b/core/apps/contracts/views/contracts.py index 3b22351..1b59015 100644 --- a/core/apps/contracts/views/contracts.py +++ b/core/apps/contracts/views/contracts.py @@ -1,7 +1,7 @@ import uuid from drf_spectacular.utils import extend_schema -from rest_framework.permissions import AllowAny, IsAdminUser # type: ignore +from rest_framework.permissions import AllowAny, IsAdminUser, IsAuthenticated # type: ignore from rest_framework.viewsets import ModelViewSet # type: ignore from rest_framework.views import APIView # type: ignore @@ -38,7 +38,7 @@ class ContractView(BaseViewSetMixin, ModelViewSet): action_permission_classes = { # type: ignore "list": [IsAdminUser], "retrieve": [IsAdminUser], - "create": [IsAdminUser], + "create": [IsAuthenticated], "update": [IsAdminUser], "destroy": [IsAdminUser], "list_file": [AllowAny], @@ -54,6 +54,15 @@ class ContractView(BaseViewSetMixin, ModelViewSet): "list_owner": RetrieveContractOwnerSerializer, } + def create( + self, + request: HttpRequest, + *args: object, + **kwargs: object, + ) -> Response: + #! TODO: checkout if user has access to create new contract. + return super().create(request, *args, **kwargs) # type: ignore + @extend_schema( summary="Get List Of Files", description="Get List Of Files"