Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -240,15 +240,20 @@ AWS_S3_OBJECT_PARAMETERS = {
|
||||
# ==============================================================================
|
||||
|
||||
AZ_IRANIAN_BANK_GATEWAYS = {
|
||||
'GATEWAYS': {
|
||||
'ZARINPAL': {
|
||||
'MERCHANT_CODE': 'Merchant-Code',
|
||||
'SANDBOX': True,
|
||||
}
|
||||
"GATEWAYS": {
|
||||
"ZARINPAL": {
|
||||
"MERCHANT_CODE": "",
|
||||
"SANDBOX": 0,
|
||||
},
|
||||
},
|
||||
'IS_SAMPLE_FORM_ENABLE': True,
|
||||
'DEFAULT_BANK': 'ZARINPAL',
|
||||
'CURRENCY': 'IRR',
|
||||
'TRACKING_CODE_QUERY_PARAM': 'tc',
|
||||
'BANK_PRIORITIES': ['ZARINPAL'],
|
||||
"IS_SAMPLE_FORM_ENABLE": True,
|
||||
"DEFAULT": "ZARINPAL",
|
||||
"CURRENCY": "IRT",
|
||||
"TRACKING_CODE_QUERY_PARAM": "tc",
|
||||
"TRACKING_CODE_LENGTH": 16,
|
||||
"SETTING_VALUE_READER_CLASS": "azbankgateways.readers.DefaultReader",
|
||||
"BANK_PRIORITIES": [
|
||||
"ZARINPAL",
|
||||
],
|
||||
"IS_SAFE_GET_GATEWAY_PAYMENT": False # better to be True
|
||||
}
|
||||
@@ -8,6 +8,9 @@ from product import views
|
||||
from account.views import CustomTokenObtainPairView
|
||||
from home.views import HomeView
|
||||
from .views import FakeAdminLoginView
|
||||
from azbankgateways.urls import az_bank_gateways_urls
|
||||
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
@@ -29,6 +32,7 @@ urlpatterns = [
|
||||
path('blogs/', include('blog.urls')),
|
||||
path('order/', include('order.urls')),
|
||||
path('home/', include('home.urls')),
|
||||
path("bankgateways/", az_bank_gateways_urls()),
|
||||
path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.1.2 on 2025-03-13 16:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0014_alter_orderitemmodel_price'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Payment',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('amount', models.PositiveIntegerField()),
|
||||
('status', models.CharField(default='Pending', max_length=50)),
|
||||
('tracking_code', models.CharField(blank=True, max_length=100)),
|
||||
('bank_type', models.CharField(max_length=100)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.1.2 on 2025-03-13 16:28
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0015_payment'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='Payment',
|
||||
new_name='PaymentModel',
|
||||
),
|
||||
]
|
||||
@@ -120,3 +120,13 @@ class OrderItemModel(models.Model):
|
||||
def __str__(self):
|
||||
return f'({self.product}) - ({self.order.user})'
|
||||
|
||||
|
||||
#TODO complate this shit
|
||||
class PaymentModel(models.Model):
|
||||
amount = models.PositiveIntegerField()
|
||||
status = models.CharField(max_length=50, default='Pending')
|
||||
tracking_code = models.CharField(max_length=100, blank=True)
|
||||
bank_type = models.CharField(max_length=100)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
def __str__(self):
|
||||
return 'payment'
|
||||
@@ -14,7 +14,7 @@ class ProductVariantSerialzier(serializers.ModelSerializer):
|
||||
category = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = ProductVariant
|
||||
fields = ['title', 'product_attributes', 'in_stock', 'price', 'discount', 'color', 'image', 'discount_amount', 'category', 'final_price']
|
||||
fields = ['id', 'title', 'product_attributes', 'in_stock', 'price', 'discount', 'color', 'image', 'discount_amount', 'category', 'final_price']
|
||||
|
||||
def get_discount_amount(self, obj):
|
||||
discount_amount = int(obj.price * (obj.discount / 100))
|
||||
|
||||
@@ -2,6 +2,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 PaymentView, callback_view
|
||||
|
||||
urlpatterns = [
|
||||
path('all', OrderlistView.as_view(), name='order-list'),
|
||||
@@ -9,6 +10,6 @@ urlpatterns = [
|
||||
path('cart/discount', ApplyDiscountView.as_view()),
|
||||
path('cart/all', CartItemClear.as_view()),
|
||||
path('cart/item/<int:pk>', CartItemViews.as_view(), name='change-item-cart'),
|
||||
# path('payment', CartView.as_view()),
|
||||
# path('', CartView.as_view()),
|
||||
path('payment', PaymentView.as_view(), name='payment'),
|
||||
path('callback', callback_view, name='callback-gateway'),
|
||||
]
|
||||
|
||||
+97
-52
@@ -7,13 +7,17 @@ from rest_framework.permissions import IsAuthenticated
|
||||
from .serializers import *
|
||||
# from cart.models import
|
||||
from rest_framework import status
|
||||
from .models import OrderItemModel, OrderModel, DiscountCode
|
||||
from .models import OrderItemModel, OrderModel, DiscountCode, PaymentModel
|
||||
from .permissons import CanDeleteCartItemPermissions
|
||||
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
|
||||
try:
|
||||
pass
|
||||
except DiscountNotAvailableError:
|
||||
pass
|
||||
|
||||
from django.urls import reverse
|
||||
"""
|
||||
|
||||
add post
|
||||
@@ -105,69 +109,110 @@ class CartView(APIView):
|
||||
class OrderlistView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
serializer_class = OrderSerializer
|
||||
pagination_class = StructurePagination
|
||||
@extend_schema(
|
||||
parameters=[
|
||||
OpenApiParameter(
|
||||
name="limit",
|
||||
description="لیمیتش",
|
||||
required=False,
|
||||
type=OpenApiTypes.INT,
|
||||
),
|
||||
OpenApiParameter(
|
||||
name="offset",
|
||||
description="افستش",
|
||||
required=False,
|
||||
type=OpenApiTypes.INT,
|
||||
),
|
||||
OpenApiParameter(
|
||||
name="status",
|
||||
description=(
|
||||
"['CART', 'ADMIN_PENDING', 'PENDING', 'POSTED', 'RECEIVED', 'CANCELED', 'BACK']"
|
||||
),
|
||||
required=False,
|
||||
type=OpenApiTypes.STR,
|
||||
),
|
||||
OpenApiParameter(
|
||||
name="sort",
|
||||
description=(
|
||||
"Sort results by one of the following fields:\n"
|
||||
"['created_at', '-created_at', 'final_price', '-final_price']"
|
||||
"\nPrefix with `-` for descending order."
|
||||
),
|
||||
required=False,
|
||||
type=OpenApiTypes.STR,
|
||||
),
|
||||
]
|
||||
)
|
||||
def get(self, request):
|
||||
user = request.user
|
||||
orders = OrderModel.objects.filter(user=user).exclude(status="CART")
|
||||
orders_ser = self.serializer_class(instance=orders, many=True, context={'request': request})
|
||||
return Response(orders_ser.data, status=status.HTTP_200_OK)
|
||||
status_filter = request.query_params.get("status", None)
|
||||
sort = request.query_params.get('sort', None)
|
||||
if status_filter in ['CART', 'ADMIN_PENDING', 'PENDING', 'POSTED', 'RECEIVED', 'CANCELED', 'BACK']:
|
||||
orders.filter(status=status_filter)
|
||||
if sort:
|
||||
if sort not in ['created_at', '-created_at', 'final_price', '-final_price']:
|
||||
return Response({'detail': 'پارامتر sort اشتباه است'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
orders = orders.order_by(sort)
|
||||
paginator = self.pagination_class()
|
||||
paginated_orders = paginator.paginate_queryset(orders, request)
|
||||
orders_ser = self.serializer_class(instance=paginated_orders, many=True, context={'request': request})
|
||||
return paginator.get_paginated_response(orders_ser.data)
|
||||
|
||||
|
||||
|
||||
# from rest_framework.views import APIView
|
||||
# from rest_framework.response import Response
|
||||
# from rest_framework import status
|
||||
# from azbankgateways import bankfactories, models as bank_models
|
||||
|
||||
# class PaymentView(APIView):
|
||||
# def post(self, request):
|
||||
# amount = request.data.get('amount')
|
||||
# user = request.user
|
||||
class PaymentView(APIView):
|
||||
def post(self, request):
|
||||
amount = 10000000
|
||||
user_mobile_number = request.user.phone
|
||||
|
||||
factory = bankfactories.BankFactory()
|
||||
try:
|
||||
bank = (
|
||||
factory.create(bank_models.BankType.ZARINPAL)
|
||||
)
|
||||
bank.set_request(request)
|
||||
bank.set_amount(amount)
|
||||
|
||||
# payment = Payment.objects.create(amount=amount, bank_type='ZARINPAL')
|
||||
bank.set_client_callback_url(request.build_absolute_uri(reverse("callback-gateway")))
|
||||
bank.set_mobile_number(user_mobile_number)
|
||||
|
||||
|
||||
# factory = bankfactories.ZarinpalBankFactory()
|
||||
# try:
|
||||
# bank = factory.create(
|
||||
# amount=amount,
|
||||
# user=user,
|
||||
# callback_url='http://.com/callback/',
|
||||
# reference_model=payment,
|
||||
# )
|
||||
# bank.ready()
|
||||
# return Response({'gateway_url': bank.redirect_url}, status=status.HTTP_200_OK)
|
||||
# except Exception as e:
|
||||
# return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
bank_record = bank.ready()
|
||||
return Response(bank.redirect_gateway().url)
|
||||
except AZBankGatewaysException as e:
|
||||
print(e)
|
||||
return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response({'gateway_url': bank.redirect_url}, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# from django.views.decorators.csrf import csrf_exempt
|
||||
# from rest_framework.decorators import api_view
|
||||
# from rest_framework.response import Response
|
||||
# from azbankgateways import bankfactories, models as bank_models
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from rest_framework.decorators import api_view
|
||||
from rest_framework.response import Response
|
||||
from azbankgateways import bankfactories, models as bank_models
|
||||
|
||||
# @csrf_exempt
|
||||
# @api_view(['POST'])
|
||||
# def callback_view(request):
|
||||
# tracking_code = request.POST.get('tracking_code')
|
||||
# payment_id = request.POST.get('payment_id')
|
||||
@csrf_exempt
|
||||
@api_view(['POST'])
|
||||
def callback_view(request):
|
||||
tracking_code = request.GET.get(settings.TRACKING_CODE_QUERY_PARAM, None)
|
||||
if not tracking_code:
|
||||
logging.debug("این لینک معتبر نیست.")
|
||||
raise Http404
|
||||
|
||||
# payment = Payment.objects.get(id=payment_id)
|
||||
# bank_type = payment.bank_type
|
||||
try:
|
||||
bank_record = bank_models.Bank.objects.get(tracking_code=tracking_code)
|
||||
except bank_models.Bank.DoesNotExist:
|
||||
logging.debug("این لینک معتبر نیست.")
|
||||
raise Http404
|
||||
|
||||
|
||||
# factory = bankfactories.BankFactory.get_bank(bank_type)
|
||||
# try:
|
||||
# result = factory.verify_transaction(tracking_code)
|
||||
# if result.is_success:
|
||||
# payment.status = 'Paid'
|
||||
# payment.tracking_code = tracking_code
|
||||
# payment.save()
|
||||
# return Response({'status': 'Payment successful'})
|
||||
# else:
|
||||
# payment.status = 'Failed'
|
||||
# payment.save()
|
||||
# return Response({'status': 'Payment failed'})
|
||||
# except Exception as e:
|
||||
# return Response({'error': str(e)})
|
||||
if bank_record.is_success:
|
||||
return HttpResponse("پرداخت با موفقیت انجام شد.")
|
||||
|
||||
|
||||
return HttpResponse(
|
||||
"پرداخت با شکست مواجه شده است. اگر پول کم شده است ظرف مدت ۴۸ ساعت پول به حساب شما بازخواهد گشت."
|
||||
)
|
||||
@@ -2,7 +2,7 @@ from .models import *
|
||||
from rest_framework import serializers
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ class ProductVariantSerialzier(serializers.ModelSerializer):
|
||||
in_pack_items = InPackItemsSerialzier(many=True)
|
||||
images = ProductImageSerailizer(many=True)
|
||||
details = ProductDetailSerializer(many=True, read_only=True)
|
||||
cart_quantity = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = ProductVariant
|
||||
exclude = ('min_price', 'sell', 'currency', 'product', 'input_price')
|
||||
@@ -60,6 +61,11 @@ class ProductVariantSerialzier(serializers.ModelSerializer):
|
||||
if view_type == 'list':
|
||||
self.fields.pop('in_pack_items', None)
|
||||
|
||||
def get_cart_quantity(self, obj):
|
||||
request = self.context.get('request')
|
||||
if not request or not request.user.is_authenticated:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
@@ -135,7 +141,7 @@ class DynamicProductSerializer(serializers.ModelSerializer):
|
||||
many=True,
|
||||
context={
|
||||
'view_type': 'list',
|
||||
'dollor_price': self.context.get('dollor_price')
|
||||
'request': self.context.get('request')
|
||||
}
|
||||
)
|
||||
return serializer.data
|
||||
|
||||
@@ -51,7 +51,7 @@ class AllCategories(APIView):
|
||||
class ProductView(APIView):
|
||||
serializer_class = DynamicProductSerializer
|
||||
permission_classes = [AllowAny]
|
||||
authentication_classes = []
|
||||
# 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'})
|
||||
|
||||
@@ -5,7 +5,7 @@ precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
// Version
|
||||
|
||||
const VERSION = "1.0.2";
|
||||
const VERSION = "1.0.3";
|
||||
|
||||
// Service Worker Installation
|
||||
self.addEventListener("install", (event) => {
|
||||
|
||||
Reference in New Issue
Block a user