From 2ccc838b1193db78e153766968122011bd9666f5 Mon Sep 17 00:00:00 2001 From: Sayyid Hamid Mahdavi Date: Tue, 29 Jul 2025 13:23:34 +0330 Subject: [PATCH] fallah --- apps/pg/admin.py | 10 +++++---- apps/pg/models.py | 34 ++++++++++++++++++++++++++++++ main/settings.py | 6 +++--- utils/exceptions.py | 50 +++++++++++++++++++++++++++++++++++++++++++++ utils/i18n.py | 14 +++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 utils/exceptions.py create mode 100644 utils/i18n.py diff --git a/apps/pg/admin.py b/apps/pg/admin.py index cf2eea9..dbde3ff 100644 --- a/apps/pg/admin.py +++ b/apps/pg/admin.py @@ -3,13 +3,15 @@ from .models import PaymentRequest, PNA, Fake class PNAAdmin(admin.ModelAdmin): - list_display = ['pna_status_code', 'pna_status_message', 'created_at', 'payment_request'] + 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 PaymentRequestAdmin(admin.ModelAdmin): - list_display = ['state', 'uuid', 'amount', 'user_id', 'created_at', 'application', 'gateway'] - search_fields = ['application__uuid','application__client_id', 'amount'] - list_filter = ['application', 'state'] + list_display = ['state', 'uuid', 'splited_amount', 'user_id', 'jajali_datetime', 'application', 'gateway'] + search_fields = ['application__uuid','application__client_id', 'amount', 'user__uuid'] + list_filter = ['application', 'state', 'gateway'] class FakeAdmin(admin.ModelAdmin): diff --git a/apps/pg/models.py b/apps/pg/models.py index 040e488..8530291 100644 --- a/apps/pg/models.py +++ b/apps/pg/models.py @@ -1,6 +1,7 @@ import urllib.parse from mimetypes import guess_all_extensions +import jdatetime from django.conf import settings from django.contrib import messages from django.db import models @@ -43,6 +44,28 @@ class PaymentRequest(models.Model): created_at = models.DateTimeField(auto_now_add=True, db_index=True) updated_at = models.DateTimeField(auto_now=True, db_index=True) + @property + def splited_amount(self): + def amount_split_3digit(value): + text = str(value)[::-1] + return ','.join([l[::-1] for l in [text[i:i + 3] for i in range(0, len(text), 3)][::-1]]) + + if self.amount: + amount_str = amount_split_3digit(str(self.amount)) + return amount_str + return + + @property + def jajali_datetime(self): + def to_jalali(value): + if value: + return jdatetime.datetime.fromgregorian(date=value, locale='fa_IR').strftime("%Y/%m/%d-%H:%M:%S") + else: + return value + + return to_jalali(self.created_at) + + def get_gateway_tools(self): if self.gateway == GatewayChoise.PNA: return PNA.objects.get(payment_request=self) @@ -155,6 +178,17 @@ class PNA(BasePGModel): client = PNAClient() + @property + def jajali_datetime(self): + def to_jalali(value): + if value: + return jdatetime.datetime.fromgregorian(date=value, locale='fa_IR').strftime("%Y/%m/%d-%H:%M:%S") + else: + return value + + return to_jalali(self.created_at) + + def make_request(self): self.payment_request.change_state(StateChoices.CREATED, StateChoices.IPG_PENDING, 'can not change state') amount = self.payment_request.amount diff --git a/main/settings.py b/main/settings.py index fa0e768..d49bd35 100644 --- a/main/settings.py +++ b/main/settings.py @@ -61,13 +61,14 @@ MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', - # 'django.middleware.locale.LocaleMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'utils.i18n.ForceAdminLanguageMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'oauth2_provider.middleware.OAuth2TokenMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - + 'utils.exceptions.ErrorMiddleware', ] OAUTH2_PROVIDER_APPLICATION_MODEL = "gooyal_oauth2.Application" @@ -144,7 +145,6 @@ DATABASES = { 'HOST': config('DB_HOST', '127.0.0.1'), 'PORT': config('DB_PORT', ''), } - } # Password validation diff --git a/utils/exceptions.py b/utils/exceptions.py new file mode 100644 index 0000000..28a4f95 --- /dev/null +++ b/utils/exceptions.py @@ -0,0 +1,50 @@ +import logging + +from rest_framework.exceptions import APIException +from rest_framework.views import exception_handler as drf_exception_handler + +logger = logging.getLogger(__name__) +def exception_handler(exc, context): + # پاسخ پیش‌فرض DRF را دریافت می‌کنیم + response = drf_exception_handler(exc, context) + + if response is not None: + # ساختار دلخواه خود را تعریف می‌کنیم + response_data = { + 'success': False, + 'status_code': response.status_code, + 'message': 'An error occurred', + 'details': {} + } + + if isinstance(exc, APIException): + response_data['message'] = exc.detail if isinstance(exc.detail, str) else "Validation error" + response_data['details'] = exc.detail if isinstance(exc.detail, dict) else {} + + response.data = response_data + + return response + + +# در فایل middleware.py +from django.http import JsonResponse + +class ErrorMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + response = self.get_response(request) + return response + + def process_exception(self, request, exception): + logger.exception(exception) + return JsonResponse( + { + "success": False, + "status_code": 500, + "message": "Internal server error", + "details": str(exception) # فقط در حالت توسعه! در تولید بهتر است لاگ شود. + }, + status=500 + ) \ No newline at end of file diff --git a/utils/i18n.py b/utils/i18n.py new file mode 100644 index 0000000..fe38f0d --- /dev/null +++ b/utils/i18n.py @@ -0,0 +1,14 @@ +from django.utils import translation + +class ForceAdminLanguageMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + if request.path.startswith('/admin/'): + translation.activate('fa') + request.LANGUAGE_CODE = 'fa' + else: + translation.activate('fa') + request.LANGUAGE_CODE = 'fa' + return self.get_response(request) \ No newline at end of file