From a52ba09460809874e3699c4fa31a548e03b083a0 Mon Sep 17 00:00:00 2001 From: Haydar Ghasemi Date: Mon, 27 Apr 2026 14:44:39 +0330 Subject: [PATCH 1/4] FEATURE(pg): add DateTimeRangeFilter to panel admin add DateTimeRangeFilter to panel admin --- apps/pg/admin.py | 3 ++- main/settings.py | 3 ++- requirements.in | 3 ++- requirements.txt | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/pg/admin.py b/apps/pg/admin.py index 7188deb..a98a722 100644 --- a/apps/pg/admin.py +++ b/apps/pg/admin.py @@ -14,6 +14,7 @@ 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__) @@ -74,7 +75,7 @@ class PaymentRequestAdmin(admin.ModelAdmin): list_display = ['state', 'check_success_again', 'uuid', 'splited_amount', 'user_id', 'jajali_datetime', 'is_registered', 'created_at', 'application', 'gateway'] search_fields = ['application__uuid', 'application__client_id', 'amount', 'user__uuid'] - list_filter = ['application', 'state', 'gateway'] + list_filter = ['application', 'state', 'gateway', ('created_at', DateTimeRangeFilter), ('updated_at', DateTimeRangeFilter)] actions = [export_exel, mark_as_registered] def changelist_view(self, request, extra_context=None): diff --git a/main/settings.py b/main/settings.py index ef8008e..b89efd6 100644 --- a/main/settings.py +++ b/main/settings.py @@ -49,6 +49,7 @@ INSTALLED_APPS = [ 'django_filters', 'jalali_date', 'django_admin_logs', + 'rangefilter', # local apps 'apps.core', @@ -63,7 +64,7 @@ MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.locale.LocaleMiddleware', - 'utils.i18n.ForceAdminLanguageMiddleware', + # 'utils.i18n.ForceAdminLanguageMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'oauth2_provider.middleware.OAuth2TokenMiddleware', diff --git a/requirements.in b/requirements.in index c6a14d0..445b91e 100644 --- a/requirements.in +++ b/requirements.in @@ -19,4 +19,5 @@ httpx django-redis xlsxwriter xlrd -django_admin_logs \ No newline at end of file +django_admin_logs +django-admin-rangefilter \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 65e6719..62c3012 100644 --- a/requirements.txt +++ b/requirements.txt @@ -182,6 +182,7 @@ zope-event==5.0 # via gevent zope-interface==7.2 # via gevent +django-admin-rangefilter==0.13.5 # The following packages are considered to be unsafe in a requirements file: # setuptools -- 2.45.3 From 6f2d5e0bd71dea8021db0fadf1fde8774d8cfa23 Mon Sep 17 00:00:00 2001 From: Haydar Ghasemi Date: Sat, 2 May 2026 13:32:07 +0330 Subject: [PATCH 2/4] run by docker via base:debian13 --- Dockerfile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1136345..843d61c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,12 @@ -FROM debian:12 +FROM base:debian13 ENV PYTHONUNBUFFERED 1 WORKDIR /app #RUN date -RUN apt update -RUN apt install gnupg2 netcat-traditional libssl-dev libcrypto++-dev lsb-release python3-pip -y -RUN apt install binutils libproj-dev gdal-bin -y -COPY requirements.txt /app/requirements.txt -RUN pip3 install --break-system-packages -r requirements.txt +#RUN apt update +#RUN apt install gnupg2 netcat-traditional libssl-dev libcrypto++-dev lsb-release python3-pip -y +#RUN apt install binutils libproj-dev gdal-bin -y +#COPY requirements.txt /app/requirements.txt +#RUN pip3 install --break-system-packages -r requirements.txt +#RUN pip3 install --break-system-packages django-admin-rangefilter==0.13.5 +#RUN pip3 install --break-system-packages setuptools #ENTRYPOINT ["./run.sh"] -- 2.45.3 From 7dcb7305079905d461d6bb466cbd6f8d017760f8 Mon Sep 17 00:00:00 2001 From: Ali Asadi Date: Wed, 19 Aug 2026 15:09:49 +0330 Subject: [PATCH 3/4] FEATURE(wallets): rename WALLET_RIAL and add WALLET_INCOME_FROM_IPG WALLET_RIAL -> WALLET_RIAL_DEPOSIT to match the naming used for the same wallet-service UUID in the advertising/settlement/promotions repos. Also adds WALLET_INCOME_FROM_IPG and wires it in: after a successful wallet charge, the commission portion is deposited separately into it (attributed to the requesting OAuth2 application) instead of never entering the wallet ledger. The income deposit is best-effort and logs on failure rather than failing an already-successful charge. Co-Authored-By: Claude Sonnet 5 --- apps/pg/models.py | 54 +++++++++++++++++++++++++++++++++++++++++++---- main/settings.py | 3 ++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/apps/pg/models.py b/apps/pg/models.py index 65d6509..587f224 100644 --- a/apps/pg/models.py +++ b/apps/pg/models.py @@ -11,7 +11,7 @@ from django.urls import reverse from oauth2_provider.settings import oauth2_settings from apps.core.models import BaseModel, BasePGModel -from apps.pg.constans import StateChoices +from apps.pg.constans import StateChoices, TypeChoices import uuid from utils.clients.wallet_client import deposit_to_user_wallet_submit, deposit_to_user_wallet_verify @@ -83,6 +83,10 @@ class PaymentRequest(models.Model): return to_jalali(self.created_at) + @property + def income_uuid(self): + return uuid.uuid5(self.uuid, 'income') + def save_commission(self): self.commission = calculate_pna_commission(self.amount) self.save(update_fields=['commission']) @@ -145,7 +149,7 @@ class PaymentRequest(models.Model): "uuid": str(self.uuid), "payee": str(self.user.uuid), "payee_type": 1, - "payee_wallet": settings.WALLET_RIAL, + "payee_wallet": settings.WALLET_RIAL_DEPOSIT, "amount": self.amount, "details": { 'description': str(_("charge via ipg")), @@ -153,7 +157,7 @@ class PaymentRequest(models.Model): 'application_details_url': '' }, } - submit_response = deposit_to_user_wallet_submit(settings.WALLET_RIAL, data) + submit_response = deposit_to_user_wallet_submit(settings.WALLET_RIAL_DEPOSIT, data) if not submit_response or not submit_response.uuid: logger.error(f"[Deposit Submit] Wallet submission failed | payment_id={self.pk}") @@ -171,7 +175,7 @@ class PaymentRequest(models.Model): return to_success def deposit_verify(self): - verify_response = deposit_to_user_wallet_verify(settings.WALLET_RIAL, self.uuid) + verify_response = deposit_to_user_wallet_verify(settings.WALLET_RIAL_DEPOSIT, self.uuid) if not verify_response: logger.error(f"[Deposit Verify] Failed to get response from wallet service | payment_id={self.pk}") @@ -205,6 +209,47 @@ class PaymentRequest(models.Model): return to_pay_success + def deposit_income_submit(self): + data = { + "uuid": str(self.income_uuid), + "payee": str(self.application_id), + "payee_type": TypeChoices.APPLICATION.value, + "payee_wallet": settings.WALLET_INCOME_FROM_IPG, + "amount": self.commission, + "details": { + 'description': str(_("ipg commission income")), + 'reference_id': str(self.uuid), + 'application_details_url': '' + }, + } + submit_response = deposit_to_user_wallet_submit(settings.WALLET_INCOME_FROM_IPG, data) + + if not submit_response or not submit_response.uuid: + raise Exception('Failed to submit income in wallet') + + return submit_response + + def deposit_income_verify(self): + verify_response = deposit_to_user_wallet_verify(settings.WALLET_INCOME_FROM_IPG, self.income_uuid) + + if not verify_response or not verify_response.uuid: + raise Exception('Failed to verify income in wallet') + + if verify_response.state != 5: + raise Exception('Failed to verify income in wallet') + + return True + + def charge_wallet_income(self): + if not self.application_id or not self.commission: + return + try: + self.deposit_income_submit() + self.deposit_income_verify() + logger.info(f"[Charge Wallet] Income charged successfully | payment_id={self.pk}") + except Exception: + logger.exception(f"[Charge Wallet] Failed to charge income | payment_id={self.pk}") + def charge_wallet_balance(self): logger.info(f"[Charge Wallet] Starting wallet charge process | payment_id={self.pk}") if self.state in [StateChoices.IPG_SUCCESS]: @@ -221,6 +266,7 @@ class PaymentRequest(models.Model): to_pay_success = self.deposit_verify() if to_pay_success: logger.info(f"[Charge Wallet] Wallet charged successfully | payment_id={self.pk}") + self.charge_wallet_income() else: logger.warning(f"[Charge Wallet] Wallet charge verification failed | payment_id={self.pk}") return bool(to_pay_success) diff --git a/main/settings.py b/main/settings.py index b89efd6..32658e3 100644 --- a/main/settings.py +++ b/main/settings.py @@ -263,7 +263,8 @@ LOGGING = get_logging_setting() PNA_CORPORATION_PIN = config('PNA_CORPORATION_PIN') WALLET_BASE_PUBLIC_URL = config('WALLET_BASE_PUBLIC_URL') -WALLET_RIAL = config('WALLET_RIAL') +WALLET_RIAL_DEPOSIT = config('WALLET_RIAL_DEPOSIT') +WALLET_INCOME_FROM_IPG = config('WALLET_INCOME_FROM_IPG') IPG_BASE_PUBLIC_URL = config('IPG_BASE_PUBLIC_URL') COMMISSION_LEVEL1 = config('COMMISSION_LEVEL1', cast=int) -- 2.45.3 From 72547b9785f9fa01f29121bed309d8a041a5d97b Mon Sep 17 00:00:00 2001 From: Ali Asadi Date: Wed, 19 Aug 2026 15:09:55 +0330 Subject: [PATCH 4/4] ignore Python bytecode caches Co-Authored-By: Claude Sonnet 5 --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c25a548..b554e32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ .idea .env media +__pycache__/ +*.pyc /clients/ /delme.py /log/accounts.log -- 2.45.3