From d440a3e8a6591a1f496ab61542cd51110b03fe63 Mon Sep 17 00:00:00 2001 From: Parsa Nazer Date: Sat, 15 Mar 2025 01:51:44 +0330 Subject: [PATCH] test payment --- backend/core/settings/base.py | 2 +- backend/order/admin.py | 23 +++++++++++++++---- .../migrations/0017_ordermodel_bank_record.py | 20 ++++++++++++++++ .../migrations/0018_delete_paymentmodel.py | 16 +++++++++++++ ...odel_bank_record_ordermodel_bank_record.py | 23 +++++++++++++++++++ ...ame_bank_record_ordermodel_bank_records.py | 18 +++++++++++++++ backend/order/models.py | 18 ++++----------- backend/order/serializers.py | 6 ++++- backend/order/tasks.py | 19 +++++++++++++++ backend/order/views.py | 19 ++++++++++----- 10 files changed, 138 insertions(+), 26 deletions(-) create mode 100644 backend/order/migrations/0017_ordermodel_bank_record.py create mode 100644 backend/order/migrations/0018_delete_paymentmodel.py create mode 100644 backend/order/migrations/0019_remove_ordermodel_bank_record_ordermodel_bank_record.py create mode 100644 backend/order/migrations/0020_rename_bank_record_ordermodel_bank_records.py create mode 100644 backend/order/tasks.py diff --git a/backend/core/settings/base.py b/backend/core/settings/base.py index 9572ade..1c00999 100644 --- a/backend/core/settings/base.py +++ b/backend/core/settings/base.py @@ -242,7 +242,7 @@ AWS_S3_OBJECT_PARAMETERS = { AZ_IRANIAN_BANK_GATEWAYS = { "GATEWAYS": { "ZARINPAL": { - "MERCHANT_CODE": "", + "MERCHANT_CODE": "9cf93a18-dc99-4e6c-8873-d37a8190a027", "SANDBOX": 0, }, }, diff --git a/backend/order/admin.py b/backend/order/admin.py index 0cc6e52..32d131c 100644 --- a/backend/order/admin.py +++ b/backend/order/admin.py @@ -7,7 +7,7 @@ from unfold.contrib.import_export.forms import ExportForm, ImportForm, Selectabl from unfold.contrib.forms.widgets import ArrayWidget, WysiwygWidget from django.contrib.postgres.fields import ArrayField from utils.admin import ModelAdmin - +from django.utils.html import format_html, format_html_join class OrderItemModelInline(StackedInline): model = OrderItemModel extra = 0 @@ -33,14 +33,27 @@ class OrderAdmin(ModelAdmin, ImportExportModelAdmin): list_filter = ['is_paid', 'status'] - list_display = ['user', 'is_paid', 'status', 'discount_code', 'address'] - readonly_fields = ('created_at',) + list_display = ['user', 'is_paid', 'status', 'discount_code', 'address', ] + readonly_fields = ('created_at', 'bank_links') compressed_fields = True warn_unsaved_form = True - + exclude = ('bank_records',) formfield_overrides = { ArrayField: { "widget": ArrayWidget, } } - inlines = [OrderItemModelInline] \ No newline at end of file + inlines = [OrderItemModelInline] + def bank_links(self, obj): + banks = obj.bank_records.all() + + if not banks.exists(): + return "-" + + return format_html_join( + "", + '{}', + [(bank.id, bank.tracking_code) for bank in banks] + ) or "-" + + bank_links.short_description = "Bank Records" \ No newline at end of file diff --git a/backend/order/migrations/0017_ordermodel_bank_record.py b/backend/order/migrations/0017_ordermodel_bank_record.py new file mode 100644 index 0000000..3e2e46e --- /dev/null +++ b/backend/order/migrations/0017_ordermodel_bank_record.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.2 on 2025-03-14 17:43 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('azbankgateways', '0005_alter_bank_bank_type_alter_bank_created_at_and_more'), + ('order', '0016_rename_payment_paymentmodel'), + ] + + operations = [ + migrations.AddField( + model_name='ordermodel', + name='bank_record', + field=models.OneToOneField(blank=True, max_length=100, null=True, on_delete=django.db.models.deletion.SET_NULL, to='azbankgateways.bank', verbose_name='رکورد بانکی'), + ), + ] diff --git a/backend/order/migrations/0018_delete_paymentmodel.py b/backend/order/migrations/0018_delete_paymentmodel.py new file mode 100644 index 0000000..14e9e00 --- /dev/null +++ b/backend/order/migrations/0018_delete_paymentmodel.py @@ -0,0 +1,16 @@ +# Generated by Django 5.1.2 on 2025-03-14 17:45 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0017_ordermodel_bank_record'), + ] + + operations = [ + migrations.DeleteModel( + name='PaymentModel', + ), + ] diff --git a/backend/order/migrations/0019_remove_ordermodel_bank_record_ordermodel_bank_record.py b/backend/order/migrations/0019_remove_ordermodel_bank_record_ordermodel_bank_record.py new file mode 100644 index 0000000..8a70985 --- /dev/null +++ b/backend/order/migrations/0019_remove_ordermodel_bank_record_ordermodel_bank_record.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.2 on 2025-03-14 18:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('azbankgateways', '0005_alter_bank_bank_type_alter_bank_created_at_and_more'), + ('order', '0018_delete_paymentmodel'), + ] + + operations = [ + migrations.RemoveField( + model_name='ordermodel', + name='bank_record', + ), + migrations.AddField( + model_name='ordermodel', + name='bank_record', + field=models.ManyToManyField(blank=True, max_length=100, null=True, to='azbankgateways.bank', verbose_name='رکورد بانکی'), + ), + ] diff --git a/backend/order/migrations/0020_rename_bank_record_ordermodel_bank_records.py b/backend/order/migrations/0020_rename_bank_record_ordermodel_bank_records.py new file mode 100644 index 0000000..8b103c6 --- /dev/null +++ b/backend/order/migrations/0020_rename_bank_record_ordermodel_bank_records.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-03-14 19:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0019_remove_ordermodel_bank_record_ordermodel_bank_record'), + ] + + operations = [ + migrations.RenameField( + model_name='ordermodel', + old_name='bank_record', + new_name='bank_records', + ), + ] diff --git a/backend/order/models.py b/backend/order/models.py index 69be701..aabb946 100644 --- a/backend/order/models.py +++ b/backend/order/models.py @@ -4,6 +4,8 @@ from product.models import ProductModel, ProductVariant, ProductImageModel from django.utils import timezone from .execptions import DiscountNotAvailableError from django_jalali.db import models as jmodels +from azbankgateways.models.banks import Bank + class DiscountCode(models.Model): code = models.CharField(max_length=50, verbose_name='کد تخفیف') @@ -42,7 +44,7 @@ class OrderModel(models.Model): ('POSTED', 'ارسال شده'), ('RECEIVED', 'تحویل شده'), ('CANCELED', 'لغو شده'), - ('BACK', 'مرجوع شده'), + ('REFUNDED', 'مرجوع شده'), ] user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='orders', verbose_name='کاربر') address = models.ForeignKey(UserAddressModel, on_delete=models.SET_NULL, related_name='orders', null=True, verbose_name='ادرس') @@ -54,8 +56,8 @@ class OrderModel(models.Model): tax = models.BigIntegerField(null=True, blank=True, verbose_name='مالیات') final_price = models.BigIntegerField(null=True, blank=True, verbose_name='قیمت نهایی') cart_total = models.BigIntegerField(null=True, blank=True, verbose_name='کل سبد خرید') - - + bank_records = models.ManyToManyField(Bank, max_length=100, verbose_name='رکورد بانکی', null=True, blank=True) + def __str__(self): return f'سفارش: {self.id}' @@ -120,13 +122,3 @@ 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' \ No newline at end of file diff --git a/backend/order/serializers.py b/backend/order/serializers.py index e4e5724..ce2edc3 100644 --- a/backend/order/serializers.py +++ b/backend/order/serializers.py @@ -96,9 +96,13 @@ class OrderSerializer(serializers.ModelSerializer): count = serializers.SerializerMethodField() images = serializers.SerializerMethodField() order_id = serializers.SerializerMethodField() + verbose_status = serializers.SerializerMethodField() class Meta: model = OrderModel - fields = ['created_at', 'status', "images", "count", "id", 'final_price', 'order_id'] + fields = ['created_at', 'status', "images", "count", "id", 'final_price', '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() diff --git a/backend/order/tasks.py b/backend/order/tasks.py new file mode 100644 index 0000000..9b1648e --- /dev/null +++ b/backend/order/tasks.py @@ -0,0 +1,19 @@ +import logging +from azbankgateways import ( + bankfactories, + models as bank_models, + default_settings as settings, +) + +# factory = bankfactories.BankFactory() + +# bank_models.Bank.objects.update_expire_records() + +# for item in bank_models.Bank.objects.filter_return_from_bank(): +# bank = factory.create( +# bank_type=item.bank_type, identifier=item.bank_choose_identifier +# ) +# bank.verify(item.tracking_code) +# bank_record = bank_models.Bank.objects.get(tracking_code=item.tracking_code) +# if bank_record.is_success: +# logging.debug("This record is verify now.", extra={"pk": bank_record.pk}) \ No newline at end of file diff --git a/backend/order/views.py b/backend/order/views.py index 468138b..a4a9309 100644 --- a/backend/order/views.py +++ b/backend/order/views.py @@ -7,7 +7,7 @@ from rest_framework.permissions import IsAuthenticated from .serializers import * # from cart.models import from rest_framework import status -from .models import OrderItemModel, OrderModel, DiscountCode, PaymentModel +from .models import OrderItemModel, OrderModel, DiscountCode from .permissons import CanDeleteCartItemPermissions from azbankgateways import bankfactories, models as bank_models from azbankgateways.exceptions import AZBankGatewaysException @@ -127,7 +127,7 @@ class OrderlistView(APIView): OpenApiParameter( name="status", description=( - "['CART', 'ADMIN_PENDING', 'PENDING', 'POSTED', 'RECEIVED', 'CANCELED', 'BACK']" + "['ADMIN_PENDING', 'PENDING', 'POSTED', 'RECEIVED', 'CANCELED', 'REFUNDED']" ), required=False, type=OpenApiTypes.STR, @@ -149,7 +149,7 @@ class OrderlistView(APIView): orders = OrderModel.objects.filter(user=user).exclude(status="CART") 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']: + if status_filter in [ 'ADMIN_PENDING', 'PENDING', 'POSTED', 'RECEIVED', 'CANCELED', 'REFUNDED']: orders.filter(status=status_filter) if sort: if sort not in ['created_at', '-created_at', 'final_price', '-final_price']: @@ -164,8 +164,10 @@ class OrderlistView(APIView): class PaymentView(APIView): + permission_classes = [IsAuthenticated] def post(self, request): - amount = 10000000 + cart_order = get_object_or_404(OrderModel, user=request.user, status='CART') + amount = 5000 user_mobile_number = request.user.phone factory = bankfactories.BankFactory() @@ -177,9 +179,13 @@ class PaymentView(APIView): bank.set_amount(amount) bank.set_client_callback_url(request.build_absolute_uri(reverse("callback-gateway"))) + print(reverse('callback-gateway')) bank.set_mobile_number(user_mobile_number) bank_record = bank.ready() + cart_order.bank_records.add(bank_record) + cart_order.save() + print(bank.redirect_gateway().url) return Response(bank.redirect_gateway().url) except AZBankGatewaysException as e: print(e) @@ -194,11 +200,12 @@ 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.http import Http404, HttpResponse @csrf_exempt -@api_view(['POST']) +@api_view(['GET']) def callback_view(request): - tracking_code = request.GET.get(settings.TRACKING_CODE_QUERY_PARAM, None) + tracking_code = request.GET.get('tc', None) if not tracking_code: logging.debug("این لینک معتبر نیست.") raise Http404