From 57e19c5abb4fe7d3637d0fa3668949b1d38eb0f5 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 17:38:00 +0330 Subject: [PATCH 01/41] test of in cart quantity --- backend/product/serializers.py | 7 ++++++- backend/product/views.py | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/product/serializers.py b/backend/product/serializers.py index cd65826..135e7da 100644 --- a/backend/product/serializers.py +++ b/backend/product/serializers.py @@ -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 diff --git a/backend/product/views.py b/backend/product/views.py index 79b1c60..41aa520 100644 --- a/backend/product/views.py +++ b/backend/product/views.py @@ -10,7 +10,7 @@ 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 # class APIView(APIView): # def __init__(self, *args, **kwargs): @@ -54,7 +54,10 @@ 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'}) + 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) + product_ser = self.serializer_class(instance=product, many=False, context={'request': request, 'view_type': 'instance', 'cart_items': cart_items_ser.data}) return Response(product_ser.data, status=status.HTTP_200_OK) From a5f881171c15fbff3fa9c97d93a0fe77a23437d7 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 17:41:16 +0330 Subject: [PATCH 02/41] import ordermodel --- backend/order/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/order/views.py b/backend/order/views.py index 5055e6b..d797810 100644 --- a/backend/order/views.py +++ b/backend/order/views.py @@ -13,6 +13,7 @@ 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: From fb3da6bcaa54d5dd526689762253eb9c1e0b724a Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 17:44:16 +0330 Subject: [PATCH 03/41] import OrderModel --- backend/product/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/product/views.py b/backend/product/views.py index 41aa520..414c5df 100644 --- a/backend/product/views.py +++ b/backend/product/views.py @@ -11,7 +11,7 @@ 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) From 0496e23680e45ef39342d34df34d174d41a52633 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 17:50:09 +0330 Subject: [PATCH 04/41] context for item serializer --- backend/product/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/product/views.py b/backend/product/views.py index 414c5df..545fc4e 100644 --- a/backend/product/views.py +++ b/backend/product/views.py @@ -56,7 +56,7 @@ class ProductView(APIView): product = get_object_or_404(ProductModel, id=pk) 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) + cart_items_ser = OrderItemSerailzier(cart_items, many=True, context={'request': request}) product_ser = self.serializer_class(instance=product, many=False, context={'request': request, 'view_type': 'instance', 'cart_items': cart_items_ser.data}) return Response(product_ser.data, status=status.HTTP_200_OK) From 58cb417ef91065ecb6ee7400667a5b385ba50dfd Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 17:56:22 +0330 Subject: [PATCH 05/41] defualy price --- .../0022_alter_orderitemmodel_price.py | 18 ++++++++++++++++++ backend/order/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 backend/order/migrations/0022_alter_orderitemmodel_price.py diff --git a/backend/order/migrations/0022_alter_orderitemmodel_price.py b/backend/order/migrations/0022_alter_orderitemmodel_price.py new file mode 100644 index 0000000..7471b3c --- /dev/null +++ b/backend/order/migrations/0022_alter_orderitemmodel_price.py @@ -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='قیمت'), + ), + ] diff --git a/backend/order/models.py b/backend/order/models.py index d79b3b0..0e5f02f 100644 --- a/backend/order/models.py +++ b/backend/order/models.py @@ -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 = 'ایتم سبد خرید' From b15aaa52711a9792a85de19a54ff2b3407a39d31 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 18:05:24 +0330 Subject: [PATCH 06/41] fix in cart quantity 12323233 --- backend/product/views.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/product/views.py b/backend/product/views.py index 545fc4e..ccc51ee 100644 --- a/backend/product/views.py +++ b/backend/product/views.py @@ -54,10 +54,15 @@ class ProductView(APIView): # authentication_classes = [] def get(self, request, pk): product = get_object_or_404(ProductModel, id=pk) - 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 = self.serializer_class(instance=product, many=False, context={'request': request, 'view_type': 'instance', 'cart_items': cart_items_ser.data}) + 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) From 75dd8abbc1e9c3b08bfef4c21e262cec895041c6 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 18:27:43 +0330 Subject: [PATCH 07/41] logout view --- backend/account/urls.py | 1 + backend/account/views.py | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/account/urls.py b/backend/account/urls.py index efdc99e..f3cb639 100644 --- a/backend/account/urls.py +++ b/backend/account/urls.py @@ -14,4 +14,5 @@ urlpatterns = [ path('address/', views.GetIDUserAddressView.as_view(), name='get-ID-address'), path('subscribe', views.SubscribeView.as_view(), name='subscibe'), path('attack/view/', views.ChangeViewAttack.as_view(), name='attack-view'), + path('logout', views.LogoutView.as_view(), name='logout'), ] \ No newline at end of file diff --git a/backend/account/views.py b/backend/account/views.py index 64d6fac..2b52687 100644 --- a/backend/account/views.py +++ b/backend/account/views.py @@ -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') \ No newline at end of file + 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) \ No newline at end of file From 062001ef0e8abfefc6cb80dd2a17f55f42391a87 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Mon, 17 Mar 2025 21:12:51 +0330 Subject: [PATCH 08/41] correct error message scurtiy breach --- backend/core/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/core/views.py b/backend/core/views.py index 6dbeb76..d57f36a 100644 --- a/backend/core/views.py +++ b/backend/core/views.py @@ -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)) \ No newline at end of file From 7ecd0325ea16a09a430e21bff577662c1dd4c923 Mon Sep 17 00:00:00 2001 From: Mamalizz Date: Tue, 18 Mar 2025 16:19:54 +0330 Subject: [PATCH 09/41] updated style --- frontend/components/cart/delivery/AddressItem.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/components/cart/delivery/AddressItem.vue b/frontend/components/cart/delivery/AddressItem.vue index 75664f7..172d3f2 100644 --- a/frontend/components/cart/delivery/AddressItem.vue +++ b/frontend/components/cart/delivery/AddressItem.vue @@ -76,12 +76,12 @@ const handleDeleteAddress = (id: number) => {
{{ !!address ? address.name : "آدرس" }} انتخاب شده @@ -97,7 +97,7 @@ const handleDeleteAddress = (id: number) => {
Date: Tue, 18 Mar 2025 16:20:17 +0330 Subject: [PATCH 10/41] changed submit discount code input and button --- .../components/cart/global/CartSummary.vue | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/frontend/components/cart/global/CartSummary.vue b/frontend/components/cart/global/CartSummary.vue index 99431d5..46e3968 100644 --- a/frontend/components/cart/global/CartSummary.vue +++ b/frontend/components/cart/global/CartSummary.vue @@ -54,29 +54,27 @@ const handleSubmitDiscountCode = () => { From 4fbc131de290a0a542160c56b9795767fc6eee24 Mon Sep 17 00:00:00 2001 From: Mamalizz Date: Tue, 18 Mar 2025 16:22:19 +0330 Subject: [PATCH 17/41] updated style --- .../components/global/ServiceHighlights.vue | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/frontend/components/global/ServiceHighlights.vue b/frontend/components/global/ServiceHighlights.vue index ea8e905..e94ea1f 100644 --- a/frontend/components/global/ServiceHighlights.vue +++ b/frontend/components/global/ServiceHighlights.vue @@ -13,48 +13,57 @@ const highlights = ref([ { icon: "/img/footer-support.svg", title: "خدمات مشتری", - description: "پشتیبانی استثنایی، راه‌حل‌های پایدار برای شما" + description: "پشتیبانی استثنایی، راه‌حل‌های پایدار برای شما", }, { icon: "/img/footer-send.svg", title: "ارسال سریع و رایگان", - description: "ارسال رایگان برای سفارش‌های بالای ۱۵۰ دلار" + description: "ارسال رایگان برای سفارش‌های بالای ۱۵۰ دلار", }, { icon: "/img/footer-share.svg", title: "معرفی به دوستان", - description: "ما را به دوستان خود معرفی کنید" + description: "ما را به دوستان خود معرفی کنید", }, { icon: "/img/footer-security.svg", title: "پرداخت امن", - description: "پرداخت شما به‌صورت امن پردازش می‌شود" - } + description: "پرداخت شما به‌صورت امن پردازش می‌شود", + }, ]); From 55d66a9449cf142f089195f0d554b3a48a0c17f7 Mon Sep 17 00:00:00 2001 From: Mamalizz Date: Tue, 18 Mar 2025 16:24:24 +0330 Subject: [PATCH 26/41] updated style --- frontend/pages/cart/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/cart/index.vue b/frontend/pages/cart/index.vue index cbca50d..8879956 100644 --- a/frontend/pages/cart/index.vue +++ b/frontend/pages/cart/index.vue @@ -30,7 +30,7 @@ const hasCartItem = computed(
Date: Tue, 18 Mar 2025 17:30:51 +0330 Subject: [PATCH 27/41] updated style --- frontend/pages/signin.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/pages/signin.vue b/frontend/pages/signin.vue index b00e574..c7d5d60 100644 --- a/frontend/pages/signin.vue +++ b/frontend/pages/signin.vue @@ -150,7 +150,7 @@ const resetForm = () => {