import logging import io import jdatetime import xlsxwriter from django.contrib import admin, messages from django.db.models import Sum from django.http import HttpResponse from django.utils import timezone from django.utils.html import format_html from django.shortcuts import redirect, get_object_or_404 from django.urls import path from .constans import StateChoices from .forms import ApplicationGatewayPolicyForm from .models import PaymentRequest, PNA, Fake, ApplicationGatewayPolicy, SEP from rangefilter.filters import DateTimeRangeFilter logger = logging.getLogger(__name__) class PNAAdmin(admin.ModelAdmin): list_display = ['pna_status_code', 'pna_status_message', 'jajali_datetime', 'payment_request'] list_filter = ['pna_status'] search_fields = ['pna_status_code', 'pna_status_message'] class SEPAdmin(admin.ModelAdmin): list_display = ['sep_status_code', 'sep_status_message', 'jajali_datetime', 'payment_request'] list_filter = ['sep_status'] search_fields = ['sep_status_code', 'sep_status_message'] @admin.action(description="export exel") def export_exel(modeladmin, request, queryset): output = io.BytesIO() workbook = xlsxwriter.Workbook(output, options={"remove_timezone": True}) worksheet = workbook.add_worksheet() for col, header in enumerate([]): worksheet.write(0, col, header) for row, payment_request in enumerate(queryset, 1): worksheet.write(row, 0, payment_request.amount) worksheet.write(row, 1, str(payment_request.pk)) worksheet.write(row, 2, str(payment_request.user.pk)) worksheet.write(row, 3, payment_request.jajali_datetime) worksheet.write(row, 4, payment_request.gateway) worksheet.write(row, 5, payment_request.get_state_display()) workbook.close() # create a response response = HttpResponse(content_type='application/vnd.ms-excel') # tell the browser what the file is named file_name = jdatetime.date.fromgregorian(date=timezone.now(), locale='fa_IR').strftime("%Y/%m/%d") response['Content-Disposition'] = f'attachment;filename="{file_name}.xlsx"' # put the spreadsheet data into the response response.write(output.getvalue()) # return the response return response @admin.action(description="mark as registered") def mark_as_registered(model_admin, request, queryset): for obj in queryset: obj.is_registered = True obj.save(update_fields=['is_registered']) class PaymentRequestAdmin(admin.ModelAdmin): list_display = ['state', 'check_success_again', 'uuid', 'amount_display', 'user_display', 'jalali_datetime_display', 'is_registered', 'created_at', 'updated_at', 'application', 'gateway'] search_fields = ['application__uuid', 'application__client_id', 'amount', 'user__uuid'] list_filter = ['application', 'state', 'gateway', ('created_at', DateTimeRangeFilter), ('updated_at', DateTimeRangeFilter)] # Every real column in list_display can be sorted ascending/descending by # clicking its header; the computed columns declare an `ordering` so they # sort by the underlying DB field. Only the "check success again" action # button stays unsortable. sortable_by = ['state', 'uuid', 'amount_display', 'user_display', 'jalali_datetime_display', 'is_registered', 'created_at', 'updated_at', 'application', 'gateway'] ordering = ['-created_at'] actions = [export_exel, mark_as_registered] @admin.display(description='Splited amount', ordering='amount') def amount_display(self, obj): return obj.splited_amount @admin.display(description='User', ordering='user') def user_display(self, obj): return obj.user_id @admin.display(description='Jajali datetime', ordering='created_at') def jalali_datetime_display(self, obj): return obj.jajali_datetime def changelist_view(self, request, extra_context=None): extra_context = extra_context or {} cl = self.get_changelist_instance(request) queryset = cl.result_list totals = queryset.aggregate( total_amount=Sum('amount'), ) extra_context['totals'] = totals return super().changelist_view(request, extra_context=extra_context) def check_success_again(self, obj): if obj.state in [StateChoices.IPG_SUCCESS, StateChoices.WALLET_SUBMIT_PENDING, StateChoices.WALLET_SUBMIT_SUCCESS]: return format_html( 'بررسی دوباره موفقیت', f'{obj.uuid}/check_success_again/' ) return '' def get_urls(self): urls = super().get_urls() custom_urls = [ path('/check_success_again/', self.admin_site.admin_view(self.check_success_again_view)) ] return custom_urls + urls def check_success_again_view(self, request, payment_request_uuid): logger.info(f"[Admin panel] Check success again for payment_request_uuid={payment_request_uuid}") payment_request: PaymentRequest = get_object_or_404(PaymentRequest, uuid=payment_request_uuid) logger.info(f"[Admin panel] initial payment_request state={payment_request.state}") if payment_request.state == StateChoices.IPG_SUCCESS: payment_request.charge_wallet_balance() elif payment_request.state == StateChoices.WALLET_SUBMIT_PENDING: payment_request.deposit_submit() elif payment_request.state == StateChoices.WALLET_SUBMIT_SUCCESS: payment_request.deposit_verify() payment_request.refresh_from_db() logger.info(f"[Admin panel] final payment_request state={payment_request.state}") self.message_user(request, f"درخواست {payment_request_uuid} بررسی شد ✅") return redirect(request.META.get("HTTP_REFERER", "..")) class FakeAdmin(admin.ModelAdmin): list_display = ['created_at'] class ApplicationGatewayPolicyAdmin(admin.ModelAdmin): form = ApplicationGatewayPolicyForm admin.site.register(PaymentRequest, PaymentRequestAdmin) admin.site.register(PNA, PNAAdmin) admin.site.register(SEP, SEPAdmin) admin.site.register(Fake, FakeAdmin) admin.site.register(ApplicationGatewayPolicy, ApplicationGatewayPolicyAdmin)