From f9a339b039d5b22779ef3bc0f44558ffa120394e Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 16:15:38 +0330 Subject: [PATCH] update order list serializer add get order view and its permission --- ..._ordermodel_tax_alter_ordermodel_status.py | 23 ++++++++++++ ...ermodel_discount_ordermodel_final_price.py | 23 ++++++++++++ backend/order/models.py | 28 +++++++------- backend/order/permissons.py | 13 ++++++- backend/order/serializers.py | 37 ++++++++++++++++--- backend/order/urls.py | 3 +- backend/order/views.py | 18 ++++++++- backend/ticket/serializers.py | 6 +-- 8 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 backend/order/migrations/0021_ordermodel_tax_alter_ordermodel_status.py create mode 100644 backend/order/migrations/0022_ordermodel_discount_ordermodel_final_price.py diff --git a/backend/order/migrations/0021_ordermodel_tax_alter_ordermodel_status.py b/backend/order/migrations/0021_ordermodel_tax_alter_ordermodel_status.py new file mode 100644 index 0000000..888434b --- /dev/null +++ b/backend/order/migrations/0021_ordermodel_tax_alter_ordermodel_status.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.2 on 2025-03-17 12:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0020_rename_bank_record_ordermodel_bank_records'), + ] + + operations = [ + migrations.AddField( + model_name='ordermodel', + name='tax', + field=models.BigIntegerField(blank=True, null=True, verbose_name='مالیات'), + ), + migrations.AlterField( + model_name='ordermodel', + name='status', + field=models.CharField(choices=[('CART', 'در سبد خرید'), ('ADMIN_PENDING', 'در انتظار تایید'), ('PENDING', 'درحال پردازش'), ('POSTED', 'ارسال شده'), ('RECEIVED', 'تحویل شده'), ('CANCELED', 'لغو شده'), ('REFUNDED', 'مرجوع شده')], max_length=20, verbose_name='وضعیت سفارش'), + ), + ] diff --git a/backend/order/migrations/0022_ordermodel_discount_ordermodel_final_price.py b/backend/order/migrations/0022_ordermodel_discount_ordermodel_final_price.py new file mode 100644 index 0000000..7ace70e --- /dev/null +++ b/backend/order/migrations/0022_ordermodel_discount_ordermodel_final_price.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.2 on 2025-03-17 12:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0021_ordermodel_tax_alter_ordermodel_status'), + ] + + operations = [ + migrations.AddField( + model_name='ordermodel', + name='discount', + field=models.BigIntegerField(blank=True, null=True, verbose_name='کل تخقیف'), + ), + migrations.AddField( + model_name='ordermodel', + name='final_price', + field=models.BigIntegerField(blank=True, null=True, verbose_name='قیمت نهایی'), + ), + ] diff --git a/backend/order/models.py b/backend/order/models.py index aabb946..d79b3b0 100644 --- a/backend/order/models.py +++ b/backend/order/models.py @@ -59,7 +59,7 @@ class OrderModel(models.Model): bank_records = models.ManyToManyField(Bank, max_length=100, verbose_name='رکورد بانکی', null=True, blank=True) def __str__(self): - return f'سفارش: {self.id}' + return f'سفارش: {self.id + 1000}' class Meta: verbose_name = 'سفارش' @@ -80,27 +80,27 @@ class OrderModel(models.Model): - def discount(self): - # total_with_item_discount = sum(item.total_with_discount() for item in self.items.all()) - # discount_percent = self.discount_code.percent - # return total_with_item_discount * ((100 - discount_percent) / 100) - pass + # def discount(self): + # # total_with_item_discount = sum(item.total_with_discount() for item in self.items.all()) + # # discount_percent = self.discount_code.percent + # # return total_with_item_discount * ((100 - discount_percent) / 100) + # pass - def tax(self): - return self.total_without_tax() * 0.2 + # def tax(self): + # return self.total_without_tax() * 0.2 - def total(self): - pass + # def total(self): + # pass # return self.total_with_discount() + self.tax() - def final_price(self): - pass + # def final_price(self): + # pass - def submit_cart(self): - pass + # def submit_cart(self): + # pass diff --git a/backend/order/permissons.py b/backend/order/permissons.py index 7b0ef86..af60575 100644 --- a/backend/order/permissons.py +++ b/backend/order/permissons.py @@ -1,7 +1,7 @@ from rest_framework.permissions import BasePermission class CanDeleteCartItemPermissions(BasePermission): - message = "شما دسترسی حذف این ایتم رو ندارید" + message = "شما دسترسی حذف این ایتم را ندارید" def has_object_permission(self, request, view, obj): if obj.order.user != request.user: @@ -12,4 +12,15 @@ class CanDeleteCartItemPermissions(BasePermission): self.message = "وضعیت سفارش سبد خرید نیست و آیتمی را نمی‌توانید حذف کنید." return False + return True + + +class GetOrderPermission(BasePermission): + message = "شما دسترسی به این سفارش را ندارید" + def has_object_permission(self, request, view, obj): + if obj.user != request.user: + return False + if obj.status != 'CART': + self.message = "سفارش در وضعیت سبد خرید است" + return False return True \ No newline at end of file diff --git a/backend/order/serializers.py b/backend/order/serializers.py index ce2edc3..2aa58b4 100644 --- a/backend/order/serializers.py +++ b/backend/order/serializers.py @@ -78,21 +78,17 @@ class CartSerializer(serializers.ModelSerializer): return None - - - def get_tax(self, obj): return f'{1000:,.0f} تومان' def get_cart_total(self, obj): - return f'{10000:,.0f} تومان' - def get_final_price(self, obj): + def get_final_price(self, obj): return f'{8000:,.0f} تومان' -class OrderSerializer(serializers.ModelSerializer): +class OrderListSerializer(serializers.ModelSerializer): count = serializers.SerializerMethodField() images = serializers.SerializerMethodField() order_id = serializers.SerializerMethodField() @@ -100,6 +96,35 @@ class OrderSerializer(serializers.ModelSerializer): class Meta: model = OrderModel fields = ['created_at', 'status', "images", "count", "id", 'final_price', 'order_id', 'verbose_status'] + read_only_fields = ['count', 'images', 'order_id', 'verbose_status'] + def get_verbose_status(self, obj): + return obj.get_status_display() + + def get_count(self, obj): + return obj.items.all().count() + + def get_images(self, obj): + image_list = [ + self.context.get('request').build_absolute_uri(image.image.url) + if (image := item.product.images.all().first()) else None + for item in obj.items.all()[:3] + ] + return filter(lambda x: x is not None, image_list) + def get_order_id(self, obj): + return obj.id + 1000 + + +class OrderGetSerializer(serializers.ModelSerializer): + count = serializers.SerializerMethodField() + images = serializers.SerializerMethodField() + order_id = serializers.SerializerMethodField() + verbose_status = serializers.SerializerMethodField() + items = OrderItemSerailzier(many=True) + address = UserAddressSerializer() + discount_code = DiscountCodeSerializer() + class Meta: + model = OrderModel + fields = ['created_at', 'status', "images", "count", "id", 'final_price', 'order_id', 'verbose_status', 'address', 'items', 'tax' , 'cart_total', 'discount_code', 'discount'] def get_verbose_status(self, obj): return obj.get_status_display() diff --git a/backend/order/urls.py b/backend/order/urls.py index c439005..969c612 100644 --- a/backend/order/urls.py +++ b/backend/order/urls.py @@ -1,7 +1,7 @@ from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include -from .views import CartItemViews, CartView, OrderlistView, CartItemClear, ApplyDiscountView +from .views import CartItemViews, CartView, OrderlistView, CartItemClear, ApplyDiscountView, OrderGetView from .views import PaymentView, callback_view urlpatterns = [ @@ -12,4 +12,5 @@ urlpatterns = [ path('cart/item/', CartItemViews.as_view(), name='change-item-cart'), path('payment', PaymentView.as_view(), name='payment'), path('callback', callback_view, name='callback-gateway'), + path('', OrderGetView.as_view(), name='order-get'), ] diff --git a/backend/order/views.py b/backend/order/views.py index bb15291..5055e6b 100644 --- a/backend/order/views.py +++ b/backend/order/views.py @@ -8,7 +8,7 @@ from .serializers import * # from cart.models import from rest_framework import status from .models import OrderItemModel, OrderModel, DiscountCode -from .permissons import CanDeleteCartItemPermissions +from .permissons import CanDeleteCartItemPermissions, GetOrderPermission from azbankgateways import bankfactories, models as bank_models from azbankgateways.exceptions import AZBankGatewaysException from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes @@ -115,7 +115,7 @@ class CartView(APIView): class OrderlistView(APIView): permission_classes = [IsAuthenticated] - serializer_class = OrderSerializer + serializer_class = OrderListSerializer pagination_class = StructurePagination @extend_schema( parameters=[ @@ -169,6 +169,20 @@ class OrderlistView(APIView): +class OrderGetView(APIView): + permission_classes = [IsAuthenticated, GetOrderPermission] + serializer_class = OrderGetSerializer + def get(self, request, pk): + order_object = get_object_or_404(OrderModel, pk=pk) + + + permission = GetOrderPermission() + if not permission.has_object_permission(request, self, order_object): + return Response({"detail": permission.message}, status=status.HTTP_403_FORBIDDEN) + + + order_ser = self.serializer_class(order_object, context={'request': request}) + return Response(order_ser.data, status=status.HTTP_200_OK) class PaymentView(APIView): permission_classes = [IsAuthenticated] diff --git a/backend/ticket/serializers.py b/backend/ticket/serializers.py index 6be7138..d99a8d2 100644 --- a/backend/ticket/serializers.py +++ b/backend/ticket/serializers.py @@ -1,7 +1,7 @@ from rest_framework import serializers from .models import Ticket, Message, Attachment from django.utils.timezone import localtime -from order.serializers import OrderSerializer +from order.serializers import OrderListSerializer from order.serializers import OrderModel class AttachmentSerializer(serializers.ModelSerializer): @@ -50,7 +50,7 @@ class TicketSerializer(serializers.ModelSerializer): messages = MessageAttachmentSerializer(many=True, read_only=True) message = MessageForTicketSerializer(write_only=True) order_id = serializers.PrimaryKeyRelatedField(queryset=OrderModel.objects.all(), write_only=True, source='order') - order = OrderSerializer(read_only=True) + order = OrderListSerializer(read_only=True) class Meta: model = Ticket exclude = ('customer', 'admin') @@ -79,7 +79,7 @@ class TicketSerializer(serializers.ModelSerializer): class TicketListSerializer(serializers.ModelSerializer): status = serializers.SerializerMethodField() ticket_category = serializers.SerializerMethodField() - order = OrderSerializer() + order = OrderListSerializer() class Meta: model = Ticket exclude = ('customer', 'admin', )