merge
This commit is contained in:
@@ -14,4 +14,5 @@ urlpatterns = [
|
||||
path('address/<int:pk>', views.GetIDUserAddressView.as_view(), name='get-ID-address'),
|
||||
path('subscribe', views.SubscribeView.as_view(), name='subscibe'),
|
||||
path('attack/view/<int:pk>', views.ChangeViewAttack.as_view(), name='attack-view'),
|
||||
path('logout', views.LogoutView.as_view(), name='logout'),
|
||||
]
|
||||
@@ -195,4 +195,27 @@ class ChangeViewAttack(View):
|
||||
attack = get_object_or_404(SecurityBreachAttemptModel, pk=pk)
|
||||
attack.viewd = not attack.viewd
|
||||
attack.save()
|
||||
return redirect('admin:account_securitybreachattemptmodel_changelist')
|
||||
return redirect('admin:account_securitybreachattemptmodel_changelist')
|
||||
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
class LogoutSerializer(serializers.Serializer):
|
||||
refresh_token = serializers.CharField(help_text="Refresh token to be blacklisted")
|
||||
|
||||
class LogoutView(APIView):
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
@extend_schema(
|
||||
request=LogoutSerializer,
|
||||
responses={205: None, 400: "Bad request (invalid token or missing data)"},
|
||||
)
|
||||
def post(self, request):
|
||||
try:
|
||||
refresh_token = request.data["refresh_token"]
|
||||
token = RefreshToken(refresh_token)
|
||||
token.blacklist()
|
||||
return Response(status=status.HTTP_205_RESET_CONTENT)
|
||||
except Exception as e:
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST)
|
||||
@@ -288,6 +288,5 @@ class FakeAdminLoginView(View):
|
||||
hacker, created = SecurityBreachAttemptModel.objects.get_or_create(ip_address=ip)
|
||||
hacker.trys += 1
|
||||
hacker.save()
|
||||
messages.error(request, "Please correct the error below.")
|
||||
messages.error(request, "Please enter the correct شماره تماس and password for a staff account. Note that both fields may be case-sensitive.")
|
||||
messages.error(request, "لطفا شماره تماس و گذرواژه را برای یک حساب کارمند وارد کنید. توجه داشته باشید که ممکن است هر دو به کوچکی و بزرگی حروف حساس باشند.")
|
||||
return render(request, 'admin/fake_login.html', self.get_context(request))
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 5.1.2 on 2025-03-17 13:04
|
||||
|
||||
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='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='قیمت نهایی'),
|
||||
),
|
||||
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='وضعیت سفارش'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.2 on 2025-03-17 14:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0021_ordermodel_discount_ordermodel_final_price_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='orderitemmodel',
|
||||
name='price',
|
||||
field=models.PositiveIntegerField(default=0, verbose_name='قیمت'),
|
||||
),
|
||||
]
|
||||
+15
-15
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ class OrderModel(models.Model):
|
||||
class OrderItemModel(models.Model):
|
||||
order = models.ForeignKey(OrderModel, on_delete=models.CASCADE, related_name='items', verbose_name='سفارش')
|
||||
quantity = models.PositiveSmallIntegerField(verbose_name="تعداد")
|
||||
price = models.PositiveIntegerField(verbose_name='قیمت', blank=True, null=True)
|
||||
price = models.PositiveIntegerField(verbose_name='قیمت', default=0)
|
||||
product = models.ForeignKey(ProductVariant, on_delete=models.PROTECT, verbose_name="محصول")
|
||||
class Meta:
|
||||
verbose_name = 'ایتم سبد خرید'
|
||||
|
||||
@@ -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
|
||||
@@ -46,13 +46,30 @@ class DiscountCodeSerializer(serializers.ModelSerializer):
|
||||
|
||||
class OrderItemSerailzier(serializers.ModelSerializer):
|
||||
product = serializers.SerializerMethodField()
|
||||
discount_amount = serializers.SerializerMethodField()
|
||||
price = serializers.SerializerMethodField()
|
||||
final_price = serializers.SerializerMethodField()
|
||||
discount = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = OrderItemModel
|
||||
exclude = ('price', 'order')
|
||||
read_only_fields = ('order', 'product', )
|
||||
exclude = ('order',)
|
||||
read_only_fields = ('order', 'product',)
|
||||
def get_product(self, obj):
|
||||
return ProductVariantSerialzier(instance=obj.product, context={'request': self.context.get('request')}).data
|
||||
|
||||
def get_discount_amount(self, obj):
|
||||
discount_amount = int(obj.price * (obj.product.discount / 100))
|
||||
return f'{(discount_amount * obj.quantity):,.0f} تومان'
|
||||
|
||||
def get_final_price(self, obj):
|
||||
final_price = obj.price - int(obj.price * (obj.product.discount / 100))
|
||||
return f'{(final_price * obj.quantity):,.0f} تومان'
|
||||
|
||||
def get_price(self, obj):
|
||||
return f'{(obj.price * obj.quantity):,.0f} تومان'
|
||||
|
||||
def get_discount(self, obj):
|
||||
return obj.product.discount
|
||||
|
||||
|
||||
|
||||
@@ -78,21 +95,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 +113,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()
|
||||
|
||||
@@ -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/<int:pk>', CartItemViews.as_view(), name='change-item-cart'),
|
||||
path('payment', PaymentView.as_view(), name='payment'),
|
||||
path('callback', callback_view, name='callback-gateway'),
|
||||
path('<int:pk>', OrderGetView.as_view(), name='order-get'),
|
||||
]
|
||||
|
||||
+25
-3
@@ -8,11 +8,12 @@ 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
|
||||
from utils.pagination import StructurePagination
|
||||
from order.models import OrderModel
|
||||
try:
|
||||
pass
|
||||
except DiscountNotAvailableError:
|
||||
@@ -45,7 +46,14 @@ class ApplyDiscountView(APIView):
|
||||
cart_order.save()
|
||||
return Response({'detail': 'کد تخفیف با موفقیت اعمال شد'}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
def delete(self, request):
|
||||
cart_order, created = OrderModel.objects.get_or_create(
|
||||
user=request.user,
|
||||
status='CART'
|
||||
)
|
||||
cart_order.discount_code = None
|
||||
cart_order.save()
|
||||
return Response({'detail': 'کد تخفیف با موفقیت حذف شد'}, status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
class CartItemClear(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
@@ -108,7 +116,7 @@ class CartView(APIView):
|
||||
|
||||
class OrderlistView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = OrderSerializer
|
||||
serializer_class = OrderListSerializer
|
||||
pagination_class = StructurePagination
|
||||
@extend_schema(
|
||||
parameters=[
|
||||
@@ -162,6 +170,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]
|
||||
|
||||
@@ -65,7 +65,12 @@ class ProductVariantSerialzier(serializers.ModelSerializer):
|
||||
request = self.context.get('request')
|
||||
if not request or not request.user.is_authenticated:
|
||||
return 0
|
||||
return 1
|
||||
cart_items = self.context.get('cart_items', [])
|
||||
if cart_items:
|
||||
for item in cart_items:
|
||||
if item['product']['id'] == obj.id:
|
||||
return item['quantity']
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
from utils.pagination import StructurePagination
|
||||
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
||||
from rest_framework.permissions import AllowAny
|
||||
|
||||
|
||||
from order.serializers import OrderItemSerailzier
|
||||
from order.models import OrderModel
|
||||
# class APIView(APIView):
|
||||
# def __init__(self, *args, **kwargs):
|
||||
# super().__init__(*args, **kwargs)
|
||||
@@ -54,7 +54,15 @@ class ProductView(APIView):
|
||||
# authentication_classes = []
|
||||
def get(self, request, pk):
|
||||
product = get_object_or_404(ProductModel, id=pk)
|
||||
product_ser = self.serializer_class(instance=product, many=False, context={'request': request, 'view_type': 'instance'})
|
||||
if request.user.is_authenticated:
|
||||
cart_obj, _ = OrderModel.objects.get_or_create(user=request.user, status='CART')
|
||||
cart_items = cart_obj.items.all()
|
||||
cart_items_ser = OrderItemSerailzier(cart_items, many=True, context={'request': request})
|
||||
product_ser_context = {'request': request, 'view_type': 'instance', 'cart_items': cart_items_ser.data}
|
||||
else:
|
||||
product_ser_context = {'request': request, 'view_type': 'instance'}
|
||||
|
||||
product_ser = self.serializer_class(instance=product, many=False, context=product_ser_context)
|
||||
return Response(product_ser.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
|
||||
@@ -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', )
|
||||
|
||||
Reference in New Issue
Block a user