From ef5ba6298c271b8372683e67724f91e7d592f41d Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Fri, 12 Sep 2025 16:16:05 +0500 Subject: [PATCH] add: add two new api --- .../finance/serializers/expence_contract.py | 71 +++++++++++++++++++ core/apps/finance/urls.py | 7 ++ core/apps/finance/views/expence_contract.py | 46 ++++++++++++ core/apps/finance/views/income_contract.py | 2 +- 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 core/apps/finance/serializers/expence_contract.py create mode 100644 core/apps/finance/views/expence_contract.py diff --git a/core/apps/finance/serializers/expence_contract.py b/core/apps/finance/serializers/expence_contract.py new file mode 100644 index 0000000..1866d26 --- /dev/null +++ b/core/apps/finance/serializers/expence_contract.py @@ -0,0 +1,71 @@ +from django.db import transaction + +from rest_framework import serializers + +from core.apps.finance.models import ExpenceContract + + +class ExpenceContractSerializer(serializers.ModelSerializer): + project_folder = serializers.SerializerMethodField(method_name='get_project_folder') + project = serializers.SerializerMethodField(method_name='get_project') + expence_type = serializers.SerializerMethodField(method_name='get_expence_type') + counterparty = serializers.SerializerMethodField(method_name='get_counterparty') + user = serializers.SerializerMethodField(method_name='get_user') + + class Meta: + model = ExpenceContract + fields = [ + 'id', 'project_folder', 'project', 'expence_type', 'counterparty', 'price', + 'currency', 'date', 'comment', 'user' + ] + extra_kwargs = { + 'id': {'read_only': True}, + 'user': {'read_only': True}, + } + + def get_user(self, obj): + return { + 'id': obj.user.id, + 'full_name': obj.user.full_name + } + + def get_counterparty(self, obj): + return { + 'id': obj.counterparty.id, + 'name': obj.counterparty.name, + } if obj.counterparty else None + + def get_expence_type(self, obj): + return { + 'id': obj.expence_type.id, + 'name': obj.expence_type.name + } if obj.expence_type else None + + def get_project(self, obj): + return { + 'id': obj.project.id, + 'name': obj.project.name + } if obj.project else None + + def get_project_folder(self, obj): + return { + 'id': obj.project_folder.id, + 'name': obj.project_folder.name + } + + + def create(self, validated_data): + with transaction.atomic(): + expence_contract = ExpenceContract.objects.create( + project_folder=validated_data.get('project_folder'), + project=validated_data.get('project'), + expence_type=validated_data.get('expence_type'), + counterparty=validated_data.get('counterparty'), + price=validated_data.get('price'), + currency=validated_data.get('currency'), + date=validated_data.get('date'), + comment=validated_data.get('comment'), + user=self.context.get('user'), + ) + return expence_contract + diff --git a/core/apps/finance/urls.py b/core/apps/finance/urls.py index 9da142d..b377f47 100644 --- a/core/apps/finance/urls.py +++ b/core/apps/finance/urls.py @@ -8,6 +8,7 @@ from core.apps.finance.views import income as income_views from core.apps.finance.views import expence_type as ex_views from core.apps.finance.views import expence as expence_views from core.apps.finance.views import income_contract as ic_views +from core.apps.finance.views import expence_contract as ec_views urlpatterns = [ @@ -72,4 +73,10 @@ urlpatterns = [ path('create/', ic_views.IncomeContractCreateApiView.as_view()), ] )), + path('expence_contract/', include( + [ + path('list/', ec_views.ExpenceContractListApiView.as_view()), + path('create/', ec_views.ExpenceContractCreateApiView.as_view()), + ] + )) ] \ No newline at end of file diff --git a/core/apps/finance/views/expence_contract.py b/core/apps/finance/views/expence_contract.py new file mode 100644 index 0000000..51c464f --- /dev/null +++ b/core/apps/finance/views/expence_contract.py @@ -0,0 +1,46 @@ +from rest_framework import generics, views +from rest_framework.response import Response + +from core.apps.finance.models import ExpenceContract +from core.apps.finance.serializers.expence_contract import ExpenceContractSerializer +from core.apps.accounts.permissions.permissions import HasRolePermission + + +class ExpenceContractCreateApiView(generics.GenericAPIView): + serializer_class = ExpenceContractSerializer + queryset = ExpenceContract.objects.all() + permission_classes = [HasRolePermission] + + def post(self, request): + serializer = self.serializer_class(data=request.data, context={'user': request.user}) + if serializer.is_valid(raise_exception=True): + serializer.save() + return Response( + { + 'success': True, + 'message': 'Expence Contract created successfully' + }, + status=201 + ) + return Response( + { + 'success': False, + 'message': 'Expence Contract create failed', + 'error': serializer.errors, + }, + status=400 + ) + + +class ExpenceContractListApiView(generics.GenericAPIView): + serializer_class = ExpenceContractSerializer + queryset = ExpenceContract.objects.select_related( + 'project_folder', 'project', 'user', 'expence_type', 'counterparty' + ) + permission_classes = [HasRolePermission] + + def get(self, request): + page = self.paginate_queryset(self.queryset) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) \ No newline at end of file diff --git a/core/apps/finance/views/income_contract.py b/core/apps/finance/views/income_contract.py index 6f8dfde..0d6a766 100644 --- a/core/apps/finance/views/income_contract.py +++ b/core/apps/finance/views/income_contract.py @@ -14,7 +14,7 @@ class IncomeContractCreateApiView(generics.GenericAPIView): permission_classes = [HasRolePermission] def post(self, request): - serializer = self.serializer_class(data=request.data) + serializer = self.serializer_class(data=request.data, context={'user': request.user}) if serializer.is_valid(raise_exception=True): serializer.save() return Response(