From 04bcd42098eff26cca63afc122020b111aaf7a7d Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Sat, 16 Aug 2025 12:20:02 +0500 Subject: [PATCH] add product apis --- core/apps/products/serializers/product.py | 87 +++++++++++++++++++++- core/apps/products/urls.py | 3 + core/apps/products/views/product.py | 90 ++++++++++++++++++++++- resources/logs/django.log.2025-08-14 | 1 + 4 files changed, 175 insertions(+), 6 deletions(-) create mode 100644 resources/logs/django.log.2025-08-14 diff --git a/core/apps/products/serializers/product.py b/core/apps/products/serializers/product.py index c78573e..267185f 100644 --- a/core/apps/products/serializers/product.py +++ b/core/apps/products/serializers/product.py @@ -1,11 +1,92 @@ +from django.db import transaction + from rest_framework import serializers -from core.apps.products.models import Product +from core.apps.products.models import Product, Folder, SubFolder, Unity class ProductListSerializer(serializers.ModelSerializer): + unity = serializers.SerializerMethodField() + class Meta: model = Product fields = [ - 'id', 'name', 'type' - ] \ No newline at end of file + 'id', 'name', 'type', 'unity' + ] + + def get_unity(self, obj): + return { + 'id': obj.unity.id, + 'value': obj.unity.value + } if obj.unity else None + + +class ProductSerializer(serializers.Serializer): + name = serializers.CharField() + type = serializers.ChoiceField(choices=Product.TYPE) + unity_id = serializers.UUIDField() + product_code = serializers.CharField(required=False) + folder_id = serializers.UUIDField() + sub_folder_id = serializers.UUIDField(required=False) + + def validate(self, data): + folder = Folder.objects.filter(id=data.get('folder_id')).first() + unity = Unity.objects.filter(id=data.get('unity_id')).first() + if not folder: + raise serializers.ValidationError("Folder not found") + if not unity: + raise serializers.ValidationError("Unity not found") + if data.get("sub_folder_id"): + sub_folder = SubFolder.objects.filter(id=data['sub_folder_id']) + if not sub_folder: + raise serializers.ValidationError("Sub Folder not found") + data['sub_folder'] = sub_folder + data['folder'] = folder + data['unity'] = unity + return data + + def create(self, validated_data): + with transaction.atomic(): + return Product.objects.create( + name=validated_data.get('name'), + type=validated_data.get('type'), + unity=validated_data.get('unity'), + folder=validated_data.get('folder'), + sub_folder=validated_data.get('sub_folder') + ) + + +class ProductUpdateSerializer(serializers.Serializer): + name = serializers.CharField(required=False) + type = serializers.ChoiceField(choices=Product.TYPE) + unity_id = serializers.UUIDField(required=False) + product_code = serializers.CharField(required=False) + folder_id = serializers.UUIDField(required=False) + sub_folder_id = serializers.UUIDField(required=False) + + def validate(self, data): + if data.get('folder_id'): + folder = Folder.objects.filter(id=data.get('folder_id')).first() + if not folder: + raise serializers.ValidationError("Folder not found") + data['folder'] = folder + if data.get('unity_id'): + unity = Unity.objects.filter(id=data.get('unity_id')).first() + if not unity: + raise serializers.ValidationError("Unity not found") + data['unity'] = unity + if data.get("sub_folder_id"): + sub_folder = SubFolder.objects.filter(id=data['sub_folder_id']) + if not sub_folder: + raise serializers.ValidationError("Sub Folder not found") + data['sub_folder'] = sub_folder + return data + + def update(self, instance, validated_data): + instance.name = validated_data.get('name', instance.name) + instance.type = validated_data.get('type', instance.type) + instance.unity = validated_data.get('unity', instance.unity) + instance.folder = validated_data.get('folder', instance.folder) + instance.sub_folder = validated_data.get('sub_folder', instance.sub_folder) + instance.save() + return instance diff --git a/core/apps/products/urls.py b/core/apps/products/urls.py index a63f30a..a702d68 100644 --- a/core/apps/products/urls.py +++ b/core/apps/products/urls.py @@ -9,6 +9,9 @@ urlpatterns = [ path('product/', include( [ path('list/', product_views.ProductListApiView.as_view()), + path('create/', product_views.ProductCreateApiView.as_view()), + path('/update/', product_views.ProductUpdateApiView.as_view()), + path('/delete/', product_views.ProductDeleteApiView.as_view()), ] )), path('unity/', include( diff --git a/core/apps/products/views/product.py b/core/apps/products/views/product.py index a8ec8a7..0646c26 100644 --- a/core/apps/products/views/product.py +++ b/core/apps/products/views/product.py @@ -1,4 +1,6 @@ -from rest_framework import generics, status +from django.shortcuts import get_object_or_404 + +from rest_framework import generics, views from rest_framework.response import Response from core.apps.products.models.product import Product @@ -9,7 +11,89 @@ from core.apps.shared.paginations.custom import CustomPageNumberPagination class ProductListApiView(generics.ListAPIView): serializer_class = serializers.ProductListSerializer + queryset = Product.objects.select_related('unity').only( + 'id', 'name', 'type', 'unity' + ) + permission_classes = [HasRolePermission] + required_permissions = ['product'] + pagination_class = CustomPageNumberPagination + + +class ProductCreateApiView(generics.GenericAPIView): + serializer_class = serializers.ProductSerializer queryset = Product.objects.all() permission_classes = [HasRolePermission] - required_permissions = [] - pagination_class = CustomPageNumberPagination \ No newline at end of file + required_permissions = ['product'] + + def post(self, request): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(raise_exception=True): + serializer.save() + return Response( + {'success': True, 'message': "product successfully created!"}, + status=201 + ) + return Response( + { + "success": False, + "message": "an error occurred while adding th product.", + "error": serializer.errors + }, + status=400 + ) + + +class ProductUpdateApiView(generics.GenericAPIView): + serializer_class = serializers.ProductUpdateSerializer + queryset = Product.objects.all() + permission_classes = [HasRolePermission] + required_permissions = ['product'] + + def put(self, request, product_id): + product = get_object_or_404(Product, id=product_id) + serializer = self.serializer_class(data=request.data, instance=product) + if serializer.is_valid(raise_exception=True): + serializer.save() + return Response( + {'success': True, 'message': 'product successfully updated!'}, + status=200 + ) + return Response( + { + 'success': False, + 'message': "an error occurred while updating the product.", + "error": serializer.errors, + }, + status=400 + ) + + def patch(self, request, product_id): + product = get_object_or_404(Product, id=product_id) + serializer = self.serializer_class(data=request.data, instance=product, partial=True) + if serializer.is_valid(raise_exception=True): + serializer.save() + return Response( + {'success': True, "message": "product successfully updated!"}, + status=200 + ) + return Response( + { + "successs": False, + "message": "an error accurred while updating the product.", + "error": serializer.errors + }, + status=400 + ) + + +class ProductDeleteApiView(views.APIView): + permission_classes = [HasRolePermission] + required_permissions = ['product'] + + def delete(self, request, product_id): + product = get_object_or_404(Product, id=product_id) + product.delete() + return Response( + {'success': True, 'message': 'product successfully deleted!'}, + status=204 + ) \ No newline at end of file diff --git a/resources/logs/django.log.2025-08-14 b/resources/logs/django.log.2025-08-14 new file mode 100644 index 0000000..c2def64 --- /dev/null +++ b/resources/logs/django.log.2025-08-14 @@ -0,0 +1 @@ +WARNING 2025-08-14 17:13:29,497 log Forbidden: /api/v1/products/folder/create/