This commit is contained in:
Sayyid Hamid Mahdavi 2026-03-09 15:11:05 +03:30
commit 6bab3b28a8
72 changed files with 3477 additions and 1655 deletions

View file

@ -1,15 +1,112 @@
from django.contrib import admin
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 .models import PaymentRequest, PNA, Fake
logger = logging.getLogger(__name__)
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']
@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', 'uuid', 'amount', 'user_id', 'created_at', 'application', 'gateway']
search_fields = ['application__uuid','application__client_id', 'amount']
list_filter = ['application', 'state']
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']
actions = [export_exel, mark_as_registered]
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(
'<a class="button" href="{}">بررسی دوباره موفقیت</a>',
f'{obj.uuid}/check_success_again/'
)
return ''
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('<uuid:payment_request_uuid>/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):

View file

@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-10-14 11:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pg', '0005_fake'),
]
operations = [
migrations.AddField(
model_name='paymentrequest',
name='is_registered',
field=models.BooleanField(default=False),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-11-10 15:10
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pg', '0006_paymentrequest_is_registered'),
]
operations = [
migrations.AddField(
model_name='paymentrequest',
name='commission',
field=models.PositiveBigIntegerField(null=True),
),
]

View file

@ -1,6 +1,8 @@
import urllib.parse
from mimetypes import guess_all_extensions
import logging
import urllib.parse
import jdatetime
from django.conf import settings
from django.contrib import messages
from django.db import models
@ -12,14 +14,15 @@ from apps.core.models import BaseModel, BasePGModel
from apps.pg.constans import StateChoices
import uuid
from utils.wallet_client import deposit_to_user_wallet_submit, withdraw_from_user_wallet_verify, \
deposit_to_user_wallet_verify
from utils.clients.wallet_client import deposit_to_user_wallet_submit, deposit_to_user_wallet_verify
from utils.commons import calculate_pna_commission
from main import settings
from utils.pna import PNAClient
from utils.sep import SEPClient
from django.utils.translation import gettext_lazy as _
logger = logging.getLogger(__name__)
class GatewayChoise(TextChoices):
FAKE = "fake", _("fake")
@ -40,12 +43,40 @@ class PaymentRequest(models.Model):
state = models.IntegerField(choices=StateChoices.choices, default=StateChoices.CREATED)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
amount = models.PositiveBigIntegerField(null=True, blank=True)
commission = models.PositiveBigIntegerField(null=True)
phone_number = models.CharField(max_length=255, null=True, blank=True)
callback_url = models.CharField(max_length=255, null=True, blank=True)
is_registered = models.BooleanField(default=False)
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 save_commission(self):
self.commission = calculate_pna_commission(self.amount)
self.save(update_fields=['commission'])
def get_gateway_tools(self):
if self.gateway == GatewayChoise.PNA:
return PNA.objects.get(payment_request=self)
@ -79,6 +110,15 @@ class PaymentRequest(models.Model):
self.save()
@property
def reference_number(self):
pna = PNA.objects.filter(payment_request=self).first()
if pna:
return pna.pk
else:
return '00000000'
# TODO: complete and use this
def change_state(self, from_state, to_state, error_message=None, **data):
if self.state == from_state:
@ -93,7 +133,72 @@ class PaymentRequest(models.Model):
else:
raise Exception(error_message)
def deposit_submit(self):
data = {
"uuid": str(self.uuid),
"payee": str(self.user.uuid),
"payee_type": 1,
"payee_wallet": settings.WALLET_RIAL,
"amount": self.amount,
"details": {
'description': str(_("charge via ipg")),
'reference_id': str(self.uuid),
'application_details_url': ''
},
}
submit_response = deposit_to_user_wallet_submit(settings.WALLET_RIAL, data)
if not submit_response or not submit_response.uuid:
logger.error(f"[Deposit Submit] Wallet submission failed | payment_id={self.pk}")
raise Exception('Failed to submit payment in wallet')
to_success = PaymentRequest.objects.filter(
pk=self.pk,
state=StateChoices.WALLET_SUBMIT_PENDING.value,
).update(
state=StateChoices.WALLET_SUBMIT_SUCCESS.value)
if not to_success:
logger.error(f"[Deposit Submit] Failed to update state to WALLET_SUBMIT_SUCCESS | payment_id={self.pk}")
raise Exception('Cannot charge balance because state')
return to_success
def deposit_verify(self):
verify_response = deposit_to_user_wallet_verify(settings.WALLET_RIAL, self.uuid)
if not verify_response:
logger.error(f"[Deposit Verify] Failed to get response from wallet service | payment_id={self.pk}")
raise Exception('Failed to get response from wallet service')
if not verify_response.uuid:
logger.error(f"[Deposit Verify] Failed to get response uuid from wallet service | payment_id={self.pk}")
raise Exception('Failed to get response uuid from wallet service')
if verify_response.state != 5:
logger.error(f"[Deposit Verify] Wallet verification failed | payment_id={self.pk}, response={verify_response}")
# to_pay_failed = PaymentRequest.objects.filter(
# pk=self.pk,
# state=StateChoices.WALLET_SUBMIT_SUCCESS.value
# ).update(
# state=StateChoices.FAILED.value,
# )
raise Exception('Failed to verify payment in wallet')
to_pay_success = PaymentRequest.objects.filter(
pk=self.pk,
state=StateChoices.WALLET_SUBMIT_SUCCESS.value
).update(
state=StateChoices.SUCCESS.value,
)
if not to_pay_success:
logger.error(f"[Deposit Verify] Failed to update state to SUCCESS | payment_id={self.pk}")
raise Exception('Failed to update state payment')
return to_pay_success
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]:
to_pending = PaymentRequest.objects.filter(
pk=self.pk,
@ -101,54 +206,15 @@ class PaymentRequest(models.Model):
).update(
state=StateChoices.WALLET_SUBMIT_PENDING.value)
if not to_pending:
logger.error(f"[Charge Wallet] Failed to update state to WALLET_SUBMIT_PENDING | payment_id={self.pk}")
raise Exception('Cannot charge balance because state')
data = {
"uuid": str(self.uuid),
"payee_id": str(self.user.uuid),
"payee_type": 1,
"amount": self.amount,
"details": {
'description': "charge via IPG",
'reference_id': str(self.uuid),
'application_details_url': ''
},
}
submit_response = deposit_to_user_wallet_submit(data)
if not submit_response.uuid:
raise Exception('Failed to submit payment in wallet')
to_success = PaymentRequest.objects.filter(
pk=self.pk,
state=StateChoices.WALLET_SUBMIT_PENDING.value,
).update(
state=StateChoices.WALLET_SUBMIT_SUCCESS.value)
if not to_success:
raise Exception('Cannot charge balance because state')
verify_response = deposit_to_user_wallet_verify(self.uuid)
if not verify_response.uuid or verify_response.state != 5:
to_pay_failed = PaymentRequest.objects.filter(
pk=self.pk,
state=StateChoices.WALLET_SUBMIT_SUCCESS.value
).update(
state=StateChoices.FAILED.value,
)
raise Exception('Failed to verify payment in wallet')
to_pay_success = PaymentRequest.objects.filter(
pk=self.pk,
state=StateChoices.WALLET_SUBMIT_SUCCESS.value
).update(
state=StateChoices.SUCCESS.value,
)
if not to_pay_success:
raise Exception('Failed to update state payment')
logger.info(f"[Charge Wallet] State updated to WALLET_SUBMIT_PENDING | payment_id={self.pk}")
self.deposit_submit()
to_pay_success = self.deposit_verify()
if to_pay_success:
logger.info(f"[Charge Wallet] Wallet charged successfully | payment_id={self.pk}")
else:
logger.warning(f"[Charge Wallet] Wallet charge verification failed | payment_id={self.pk}")
return bool(to_pay_success)
@ -166,9 +232,20 @@ 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
amount = self.payment_request.amount + self.payment_request.commission
description = 'from addwin ipg'
callback_url = urllib.parse.urljoin(
settings.IPG_BASE_PUBLIC_URL,
@ -199,7 +276,7 @@ class PNA(BasePGModel):
def confirm_request(self, request=None):
if self.payment_request.state not in [StateChoices.IPG_PENDING]:
messages.error(request, "وضعیت تراکنش در حالت مناسبی نیست.")
return
return False, "وضعیت تراکنش در حالت مناسبی نیست."
print(dict(request.POST))
post_dict = dict(request.POST)
@ -223,13 +300,16 @@ class PNA(BasePGModel):
self.payment_request.charge_wallet_balance()
messages.success(request, 'شارژ انجام شد')
return True, 'شارژ انجام شد'
except Exception as e:
print(e)
messages.error(request, str(e))
return False, "خطایی رخ داده است."
else:
print(request.POST)
messages.error(request, "نتیجه تراکنش از سمت درگاه دریافت نشد.")
return False, "نتیجه تراکنش از سمت درگاه دریافت نشد."
def reverse_request(self):
raise NotImplementedError()

View file

@ -39,3 +39,7 @@ class ApplicationPaymentRequestSerializer(serializers.ModelSerializer):
read_only_fields = ['uuid', 'updated_at', 'state', 'created_at']
class CommissionSerializer(serializers.Serializer):
amount = serializers.IntegerField()
commission = serializers.IntegerField(read_only=True)

View file

@ -1,12 +1,13 @@
from django.urls import path, include
from .views import PaymentRequestView, PaymentRequestCreateApiView, PaymentConfirmView, \
ApplicationPaymentRequestCreateApiView
ApplicationPaymentRequestCreateApiView, CalculateCommissionView
app_name = "pg"
urlpatterns = [
path('page/charge/<uuid>/', PaymentRequestView.as_view(), name='payment-request-view'),
path('page/callback/<uuid>/', PaymentConfirmView.as_view(), name='payment-confirm-view'),
path('page/confirm/<uuid>/', PaymentConfirmView.as_view(), name='payment-confirm-view'),
path('api/charge_create/', PaymentRequestCreateApiView.as_view(), name='charge-request-create-api-view'),
path('api/application/charge_create/<uuid>', ApplicationPaymentRequestCreateApiView.as_view(), name='application-user-charge-request-create-api-view'),
path('api/calculate_commission/', CalculateCommissionView.as_view(), name='calculate-commission-view'),
]

View file

@ -1,24 +1,42 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import UpdateView, DetailView
from oauth2_provider.contrib.rest_framework import TokenHasScope, IsAuthenticatedOrTokenHasScope
from django.views.generic import UpdateView
from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
from rest_framework import generics
from rest_framework.response import Response
from rest_framework.views import APIView
from drf_spectacular.utils import extend_schema
from django.shortcuts import render
from .forms import PaymentRequestForm
from .models import PaymentRequest, GatewayChoise
from .serializers import PaymentRequestSerializer, ApplicationPaymentRequestSerializer
from utils.commons import calculate_pna_commission
from .constans import StateChoices
from .forms import PaymentRequestForm
from .models import PaymentRequest
from .serializers import PaymentRequestSerializer, CommissionSerializer
from ..core.models import BasePGModel
from ..gooyal_oauth2.utils import get_application
from ..users.models import User
class CalculateCommissionView(APIView):
@extend_schema(
request=CommissionSerializer,
responses=CommissionSerializer
)
def post(self, request):
serializer = CommissionSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
amount = serializer.validated_data['amount']
commission = calculate_pna_commission(amount)
serializer = CommissionSerializer({
"amount": amount,
"commission": commission
})
return Response(serializer.data)
class PaymentRequestCreateApiView(generics.CreateAPIView):
permission_classes = [IsAuthenticatedOrTokenHasScope]
serializer_class = PaymentRequestSerializer
@ -50,12 +68,41 @@ class ApplicationPaymentRequestCreateApiView(generics.CreateAPIView):
@method_decorator(csrf_exempt, name='dispatch')
class PaymentRequestView(UpdateView):
template_name = 'pg/payment-request.html'
template_name = 'pg/payment_request.html'
form_class = PaymentRequestForm
# pk_url_kwarg = 'uuid'
slug_field = 'uuid'
slug_url_kwarg = 'uuid'
# TODO: remove it in future
def get(self, request, *args, **kwargs):
charge_request: PaymentRequest = self.get_object()
charge_request.set_gateway({'pna': True})
charge_request.save_commission()
tool = charge_request.get_gateway_tools()
tool.make_request()
charge_request.refresh_from_db()
if charge_request.state == StateChoices.FAILED:
return render(request, 'pg/payment_failure.html', {
'object': charge_request
})
redirect_url = tool.get_pg_page_url()
return HttpResponseRedirect(redirect_url)
# TODO: remove it in future
def post(self, request, *args, **kwargs):
charge_request: PaymentRequest = self.get_object()
charge_request.set_gateway({'pna': True})
tool = charge_request.get_gateway_tools()
tool.make_request()
charge_request.refresh_from_db()
if charge_request.state == StateChoices.FAILED:
return render(request, 'pg/payment_failure.html', {
'object': charge_request
})
redirect_url = tool.get_pg_page_url()
return HttpResponseRedirect(redirect_url)
def get_queryset(self):
# return ChargeRequest.objects.all()
# return Charge.objects.filter(state__in=[StateChoices.CREATED.value, StateChoices.SUCCESS.value])
@ -91,7 +138,8 @@ class PaymentRequestView(UpdateView):
@method_decorator(csrf_exempt, name='dispatch')
class PaymentConfirmView(UpdateView):
template_name = 'pg/payment-confirm.html'
# template_name = 'pg/payment_confirm.html'
template_name = 'pg/payment_failure.html'
form_class = PaymentRequestForm
# pk_url_kwarg = 'uuid'
slug_field = 'uuid'
@ -107,7 +155,14 @@ class PaymentConfirmView(UpdateView):
print(kwargs)
self.object = self.get_object()
tool = self.object.get_gateway_tools()
tool.confirm_request(request)
# state, message = tool.confirm_request(request)
# if state:
# self.template_name = 'pg/payment_success.html'
#
#
# # TODO:
# context = self.get_context_data(object=self.object)
# context['message'] = message
context = self.get_context_data()
return self.render_to_response(context)
@ -122,37 +177,13 @@ class PaymentConfirmView(UpdateView):
if 'redirect-to-app' in request.POST:
response = HttpResponse(status=302)
response['Location'] = self.object.callback_url
response['Location'] = self.object.callback_url + f'?state={self.object.state}'
return response
tool = self.object.get_gateway_tools()
tool.confirm_request(request)
state, message = tool.confirm_request(request)
if state:
self.template_name = 'pg/payment_success.html'
context = self.get_context_data(object=self.object)
context['message'] = message
return self.render_to_response(context)
# def form_valid(self, form):
# self.object = form.save()
# charge_request: ChargeRequest = self.get_object()
# try:
#
# # transaction = Transaction.objects.create(
# # uuid=charge.uuid,
# # payee_id=charge.user.pk,
# # payee_type=1,
# # payer_id=payer_pk,
# # payer_type=2,
# # amount=amount,
# # details={'description': 'شارژ مجازی کیف پول'}
# # )
# # transaction.submit()
# # transaction.verify()
# # charge.change_state(from_state=StateChoices.PENDING.value, to_state=StateChoices.SUCCESS.value)
#
# except Exception as e:
# print(e)
# messages.error(self.request, 'خطایی رخ داده است')
# charge_request.change_state(from_state=StateChoices.PENDING.value, to_state=StateChoices.EXPECTED_FAILURE.value)
#
# return HttpResponseRedirect(self.get_success_url())

View file

@ -1,126 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.application_balance import ApplicationBalance
from ...types import Response
def _get_kwargs() -> dict[str, Any]:
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/wallet/api/application/balance",
}
return _kwargs
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[ApplicationBalance]:
if response.status_code == 200:
response_200 = ApplicationBalance.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[ApplicationBalance]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)
def sync_detailed(
*,
client: AuthenticatedClient,
) -> Response[ApplicationBalance]:
"""API for getting specified user or application balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[ApplicationBalance]
"""
kwargs = _get_kwargs()
response = client.get_httpx_client().request(
**kwargs,
)
return _build_response(client=client, response=response)
def sync(
*,
client: AuthenticatedClient,
) -> Optional[ApplicationBalance]:
"""API for getting specified user or application balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
ApplicationBalance
"""
return sync_detailed(
client=client,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
) -> Response[ApplicationBalance]:
"""API for getting specified user or application balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[ApplicationBalance]
"""
kwargs = _get_kwargs()
response = await client.get_async_httpx_client().request(**kwargs)
return _build_response(client=client, response=response)
async def asyncio(
*,
client: AuthenticatedClient,
) -> Optional[ApplicationBalance]:
"""API for getting specified user or application balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
ApplicationBalance
"""
return (
await asyncio_detailed(
client=client,
)
).parsed

View file

@ -1,122 +0,0 @@
from http import HTTPStatus
from typing import Any, Optional, Union
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.my_wallet import MyWallet
from ...types import Response
def _get_kwargs() -> dict[str, Any]:
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/wallet/api/wallet/balance",
}
return _kwargs
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[MyWallet]:
if response.status_code == 200:
response_200 = MyWallet.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[MyWallet]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)
def sync_detailed(
*,
client: AuthenticatedClient,
) -> Response[MyWallet]:
"""API for getting authenticated user balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[MyWallet]
"""
kwargs = _get_kwargs()
response = client.get_httpx_client().request(
**kwargs,
)
return _build_response(client=client, response=response)
def sync(
*,
client: AuthenticatedClient,
) -> Optional[MyWallet]:
"""API for getting authenticated user balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
MyWallet
"""
return sync_detailed(
client=client,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
) -> Response[MyWallet]:
"""API for getting authenticated user balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[MyWallet]
"""
kwargs = _get_kwargs()
response = await client.get_async_httpx_client().request(**kwargs)
return _build_response(client=client, response=response)
async def asyncio(
*,
client: AuthenticatedClient,
) -> Optional[MyWallet]:
"""API for getting authenticated user balance.
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
MyWallet
"""
return (
await asyncio_detailed(
client=client,
)
).parsed

View file

@ -1,27 +0,0 @@
"""Contains all the data models used in inputs/outputs"""
from .application_balance import ApplicationBalance
from .application_deposit import ApplicationDeposit
from .application_transaction import ApplicationTransaction
from .application_withdraw import ApplicationWithdraw
from .my_wallet import MyWallet
from .paginated_application_transaction_list import PaginatedApplicationTransactionList
from .paginated_user_transaction_list import PaginatedUserTransactionList
from .payee_type_enum import PayeeTypeEnum
from .payer_type_enum import PayerTypeEnum
from .state_enum import StateEnum
from .user_transaction import UserTransaction
__all__ = (
"ApplicationBalance",
"ApplicationDeposit",
"ApplicationTransaction",
"ApplicationWithdraw",
"MyWallet",
"PaginatedApplicationTransactionList",
"PaginatedUserTransactionList",
"PayeeTypeEnum",
"PayerTypeEnum",
"StateEnum",
"UserTransaction",
)

View file

@ -1,58 +0,0 @@
from typing import Any, TypeVar, Union
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from ..types import UNSET, Unset
T = TypeVar("T", bound="ApplicationBalance")
@_attrs_define
class ApplicationBalance:
"""
Attributes:
balance (Union[Unset, int]):
"""
balance: Union[Unset, int] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
balance = self.balance
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if balance is not UNSET:
field_dict["balance"] = balance
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
d = src_dict.copy()
balance = d.pop("balance", UNSET)
application_balance = cls(
balance=balance,
)
application_balance.additional_properties = d
return application_balance
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,235 +0,0 @@
import datetime
from typing import Any, TypeVar, Union, cast
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.payee_type_enum import PayeeTypeEnum
from ..models.payer_type_enum import PayerTypeEnum
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="ApplicationDeposit")
@_attrs_define
class ApplicationDeposit:
"""
Attributes:
uuid (UUID):
payer_id (Union[None, UUID]):
payer_type (Union[None, PayerTypeEnum]):
payee_id (UUID):
created_at (Union[None, datetime.datetime]):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (Union[None, datetime.datetime]):
payee_type (Union[None, PayeeTypeEnum, Unset]):
details (Union[Unset, Any]):
"""
uuid: UUID
payer_id: Union[None, UUID]
payer_type: Union[None, PayerTypeEnum]
payee_id: UUID
created_at: Union[None, datetime.datetime]
state: StateEnum
amount: int
updated_at: Union[None, datetime.datetime]
payee_type: Union[None, PayeeTypeEnum, Unset] = UNSET
details: Union[Unset, Any] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
uuid = str(self.uuid)
payer_id: Union[None, str]
if isinstance(self.payer_id, UUID):
payer_id = str(self.payer_id)
else:
payer_id = self.payer_id
payer_type: Union[None, int]
if isinstance(self.payer_type, PayerTypeEnum):
payer_type = self.payer_type.value
else:
payer_type = self.payer_type
payee_id = str(self.payee_id)
created_at: Union[None, str]
if isinstance(self.created_at, datetime.datetime):
created_at = self.created_at.isoformat()
else:
created_at = self.created_at
state = self.state.value
amount = self.amount
updated_at: Union[None, str]
if isinstance(self.updated_at, datetime.datetime):
updated_at = self.updated_at.isoformat()
else:
updated_at = self.updated_at
payee_type: Union[None, Unset, int]
if isinstance(self.payee_type, Unset):
payee_type = UNSET
elif isinstance(self.payee_type, PayeeTypeEnum):
payee_type = self.payee_type.value
else:
payee_type = self.payee_type
details = self.details
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"uuid": uuid,
"payer_id": payer_id,
"payer_type": payer_type,
"payee_id": payee_id,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
}
)
if payee_type is not UNSET:
field_dict["payee_type"] = payee_type
if details is not UNSET:
field_dict["details"] = details
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
d = src_dict.copy()
uuid = UUID(d.pop("uuid"))
def _parse_payer_id(data: object) -> Union[None, UUID]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
payer_id_type_0 = UUID(data)
return payer_id_type_0
except: # noqa: E722
pass
return cast(Union[None, UUID], data)
payer_id = _parse_payer_id(d.pop("payer_id"))
def _parse_payer_type(data: object) -> Union[None, PayerTypeEnum]:
if data is None:
return data
try:
if not isinstance(data, int):
raise TypeError()
payer_type_type_0 = PayerTypeEnum(data)
return payer_type_type_0
except: # noqa: E722
pass
return cast(Union[None, PayerTypeEnum], data)
payer_type = _parse_payer_type(d.pop("payer_type"))
payee_id = UUID(d.pop("payee_id"))
def _parse_created_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
created_at_type_0 = isoparse(data)
return created_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
created_at = _parse_created_at(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
def _parse_updated_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
updated_at_type_0 = isoparse(data)
return updated_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
updated_at = _parse_updated_at(d.pop("updated_at"))
def _parse_payee_type(data: object) -> Union[None, PayeeTypeEnum, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, int):
raise TypeError()
payee_type_type_0 = PayeeTypeEnum(data)
return payee_type_type_0
except: # noqa: E722
pass
return cast(Union[None, PayeeTypeEnum, Unset], data)
payee_type = _parse_payee_type(d.pop("payee_type", UNSET))
details = d.pop("details", UNSET)
application_deposit = cls(
uuid=uuid,
payer_id=payer_id,
payer_type=payer_type,
payee_id=payee_id,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
payee_type=payee_type,
details=details,
)
application_deposit.additional_properties = d
return application_deposit
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,238 +0,0 @@
import datetime
from typing import Any, TypeVar, Union, cast
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.payer_type_enum import PayerTypeEnum
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="ApplicationTransaction")
@_attrs_define
class ApplicationTransaction:
"""
Attributes:
uuid (UUID):
payee_id (UUID):
payee_type (UUID):
created_at (Union[None, datetime.datetime]):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (Union[None, datetime.datetime]):
details (Any):
role (str):
payer_id (Union[None, UUID, Unset]):
payer_type (Union[None, PayerTypeEnum, Unset]):
delay (Union[Unset, int]):
"""
uuid: UUID
payee_id: UUID
payee_type: UUID
created_at: Union[None, datetime.datetime]
state: StateEnum
amount: int
updated_at: Union[None, datetime.datetime]
details: Any
role: str
payer_id: Union[None, UUID, Unset] = UNSET
payer_type: Union[None, PayerTypeEnum, Unset] = UNSET
delay: Union[Unset, int] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
uuid = str(self.uuid)
payee_id = str(self.payee_id)
payee_type = str(self.payee_type)
created_at: Union[None, str]
if isinstance(self.created_at, datetime.datetime):
created_at = self.created_at.isoformat()
else:
created_at = self.created_at
state = self.state.value
amount = self.amount
updated_at: Union[None, str]
if isinstance(self.updated_at, datetime.datetime):
updated_at = self.updated_at.isoformat()
else:
updated_at = self.updated_at
details = self.details
role = self.role
payer_id: Union[None, Unset, str]
if isinstance(self.payer_id, Unset):
payer_id = UNSET
elif isinstance(self.payer_id, UUID):
payer_id = str(self.payer_id)
else:
payer_id = self.payer_id
payer_type: Union[None, Unset, int]
if isinstance(self.payer_type, Unset):
payer_type = UNSET
elif isinstance(self.payer_type, PayerTypeEnum):
payer_type = self.payer_type.value
else:
payer_type = self.payer_type
delay = self.delay
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"uuid": uuid,
"payee_id": payee_id,
"payee_type": payee_type,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
"details": details,
"role": role,
}
)
if payer_id is not UNSET:
field_dict["payer_id"] = payer_id
if payer_type is not UNSET:
field_dict["payer_type"] = payer_type
if delay is not UNSET:
field_dict["delay"] = delay
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
d = src_dict.copy()
uuid = UUID(d.pop("uuid"))
payee_id = UUID(d.pop("payee_id"))
payee_type = UUID(d.pop("payee_type"))
def _parse_created_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
created_at_type_0 = isoparse(data)
return created_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
created_at = _parse_created_at(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
def _parse_updated_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
updated_at_type_0 = isoparse(data)
return updated_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
updated_at = _parse_updated_at(d.pop("updated_at"))
details = d.pop("details")
role = d.pop("role")
def _parse_payer_id(data: object) -> Union[None, UUID, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, str):
raise TypeError()
payer_id_type_0 = UUID(data)
return payer_id_type_0
except: # noqa: E722
pass
return cast(Union[None, UUID, Unset], data)
payer_id = _parse_payer_id(d.pop("payer_id", UNSET))
def _parse_payer_type(data: object) -> Union[None, PayerTypeEnum, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, int):
raise TypeError()
payer_type_type_0 = PayerTypeEnum(data)
return payer_type_type_0
except: # noqa: E722
pass
return cast(Union[None, PayerTypeEnum, Unset], data)
payer_type = _parse_payer_type(d.pop("payer_type", UNSET))
delay = d.pop("delay", UNSET)
application_transaction = cls(
uuid=uuid,
payee_id=payee_id,
payee_type=payee_type,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
details=details,
role=role,
payer_id=payer_id,
payer_type=payer_type,
delay=delay,
)
application_transaction.additional_properties = d
return application_transaction
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,239 +0,0 @@
import datetime
from typing import Any, TypeVar, Union, cast
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.payee_type_enum import PayeeTypeEnum
from ..models.payer_type_enum import PayerTypeEnum
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="ApplicationWithdraw")
@_attrs_define
class ApplicationWithdraw:
"""
Attributes:
uuid (UUID):
payee_id (UUID):
payee_type (Union[None, PayeeTypeEnum]):
created_at (Union[None, datetime.datetime]):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (Union[None, datetime.datetime]):
details (Any):
payer_id (Union[None, UUID, Unset]):
payer_type (Union[None, PayerTypeEnum, Unset]):
"""
uuid: UUID
payee_id: UUID
payee_type: Union[None, PayeeTypeEnum]
created_at: Union[None, datetime.datetime]
state: StateEnum
amount: int
updated_at: Union[None, datetime.datetime]
details: Any
payer_id: Union[None, UUID, Unset] = UNSET
payer_type: Union[None, PayerTypeEnum, Unset] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
uuid = str(self.uuid)
payee_id = str(self.payee_id)
payee_type: Union[None, int]
if isinstance(self.payee_type, PayeeTypeEnum):
payee_type = self.payee_type.value
else:
payee_type = self.payee_type
created_at: Union[None, str]
if isinstance(self.created_at, datetime.datetime):
created_at = self.created_at.isoformat()
else:
created_at = self.created_at
state = self.state.value
amount = self.amount
updated_at: Union[None, str]
if isinstance(self.updated_at, datetime.datetime):
updated_at = self.updated_at.isoformat()
else:
updated_at = self.updated_at
details = self.details
payer_id: Union[None, Unset, str]
if isinstance(self.payer_id, Unset):
payer_id = UNSET
elif isinstance(self.payer_id, UUID):
payer_id = str(self.payer_id)
else:
payer_id = self.payer_id
payer_type: Union[None, Unset, int]
if isinstance(self.payer_type, Unset):
payer_type = UNSET
elif isinstance(self.payer_type, PayerTypeEnum):
payer_type = self.payer_type.value
else:
payer_type = self.payer_type
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"uuid": uuid,
"payee_id": payee_id,
"payee_type": payee_type,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
"details": details,
}
)
if payer_id is not UNSET:
field_dict["payer_id"] = payer_id
if payer_type is not UNSET:
field_dict["payer_type"] = payer_type
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
d = src_dict.copy()
uuid = UUID(d.pop("uuid"))
payee_id = UUID(d.pop("payee_id"))
def _parse_payee_type(data: object) -> Union[None, PayeeTypeEnum]:
if data is None:
return data
try:
if not isinstance(data, int):
raise TypeError()
payee_type_type_0 = PayeeTypeEnum(data)
return payee_type_type_0
except: # noqa: E722
pass
return cast(Union[None, PayeeTypeEnum], data)
payee_type = _parse_payee_type(d.pop("payee_type"))
def _parse_created_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
created_at_type_0 = isoparse(data)
return created_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
created_at = _parse_created_at(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
def _parse_updated_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
updated_at_type_0 = isoparse(data)
return updated_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
updated_at = _parse_updated_at(d.pop("updated_at"))
details = d.pop("details")
def _parse_payer_id(data: object) -> Union[None, UUID, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, str):
raise TypeError()
payer_id_type_0 = UUID(data)
return payer_id_type_0
except: # noqa: E722
pass
return cast(Union[None, UUID, Unset], data)
payer_id = _parse_payer_id(d.pop("payer_id", UNSET))
def _parse_payer_type(data: object) -> Union[None, PayerTypeEnum, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, int):
raise TypeError()
payer_type_type_0 = PayerTypeEnum(data)
return payer_type_type_0
except: # noqa: E722
pass
return cast(Union[None, PayerTypeEnum, Unset], data)
payer_type = _parse_payer_type(d.pop("payer_type", UNSET))
application_withdraw = cls(
uuid=uuid,
payee_id=payee_id,
payee_type=payee_type,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
details=details,
payer_id=payer_id,
payer_type=payer_type,
)
application_withdraw.additional_properties = d
return application_withdraw
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,58 +0,0 @@
from typing import Any, TypeVar, Union
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from ..types import UNSET, Unset
T = TypeVar("T", bound="MyWallet")
@_attrs_define
class MyWallet:
"""
Attributes:
balance (Union[Unset, int]):
"""
balance: Union[Unset, int] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
balance = self.balance
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if balance is not UNSET:
field_dict["balance"] = balance
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
d = src_dict.copy()
balance = d.pop("balance", UNSET)
my_wallet = cls(
balance=balance,
)
my_wallet.additional_properties = d
return my_wallet
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,9 +0,0 @@
from enum import IntEnum
class PayeeTypeEnum(IntEnum):
VALUE_1 = 1
VALUE_2 = 2
def __str__(self) -> str:
return str(self.value)

View file

@ -1,9 +0,0 @@
from enum import IntEnum
class PayerTypeEnum(IntEnum):
VALUE_1 = 1
VALUE_2 = 2
def __str__(self) -> str:
return str(self.value)

View file

@ -1,238 +0,0 @@
import datetime
from typing import Any, TypeVar, Union, cast
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.payer_type_enum import PayerTypeEnum
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="UserTransaction")
@_attrs_define
class UserTransaction:
"""
Attributes:
uuid (UUID):
payee_id (UUID):
payee_type (UUID):
created_at (Union[None, datetime.datetime]):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (Union[None, datetime.datetime]):
details (Any):
role (int):
payer_id (Union[None, UUID, Unset]):
payer_type (Union[None, PayerTypeEnum, Unset]):
delay (Union[Unset, int]):
"""
uuid: UUID
payee_id: UUID
payee_type: UUID
created_at: Union[None, datetime.datetime]
state: StateEnum
amount: int
updated_at: Union[None, datetime.datetime]
details: Any
role: int
payer_id: Union[None, UUID, Unset] = UNSET
payer_type: Union[None, PayerTypeEnum, Unset] = UNSET
delay: Union[Unset, int] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
uuid = str(self.uuid)
payee_id = str(self.payee_id)
payee_type = str(self.payee_type)
created_at: Union[None, str]
if isinstance(self.created_at, datetime.datetime):
created_at = self.created_at.isoformat()
else:
created_at = self.created_at
state = self.state.value
amount = self.amount
updated_at: Union[None, str]
if isinstance(self.updated_at, datetime.datetime):
updated_at = self.updated_at.isoformat()
else:
updated_at = self.updated_at
details = self.details
role = self.role
payer_id: Union[None, Unset, str]
if isinstance(self.payer_id, Unset):
payer_id = UNSET
elif isinstance(self.payer_id, UUID):
payer_id = str(self.payer_id)
else:
payer_id = self.payer_id
payer_type: Union[None, Unset, int]
if isinstance(self.payer_type, Unset):
payer_type = UNSET
elif isinstance(self.payer_type, PayerTypeEnum):
payer_type = self.payer_type.value
else:
payer_type = self.payer_type
delay = self.delay
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"uuid": uuid,
"payee_id": payee_id,
"payee_type": payee_type,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
"details": details,
"role": role,
}
)
if payer_id is not UNSET:
field_dict["payer_id"] = payer_id
if payer_type is not UNSET:
field_dict["payer_type"] = payer_type
if delay is not UNSET:
field_dict["delay"] = delay
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
d = src_dict.copy()
uuid = UUID(d.pop("uuid"))
payee_id = UUID(d.pop("payee_id"))
payee_type = UUID(d.pop("payee_type"))
def _parse_created_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
created_at_type_0 = isoparse(data)
return created_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
created_at = _parse_created_at(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
def _parse_updated_at(data: object) -> Union[None, datetime.datetime]:
if data is None:
return data
try:
if not isinstance(data, str):
raise TypeError()
updated_at_type_0 = isoparse(data)
return updated_at_type_0
except: # noqa: E722
pass
return cast(Union[None, datetime.datetime], data)
updated_at = _parse_updated_at(d.pop("updated_at"))
details = d.pop("details")
role = d.pop("role")
def _parse_payer_id(data: object) -> Union[None, UUID, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, str):
raise TypeError()
payer_id_type_0 = UUID(data)
return payer_id_type_0
except: # noqa: E722
pass
return cast(Union[None, UUID, Unset], data)
payer_id = _parse_payer_id(d.pop("payer_id", UNSET))
def _parse_payer_type(data: object) -> Union[None, PayerTypeEnum, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, int):
raise TypeError()
payer_type_type_0 = PayerTypeEnum(data)
return payer_type_type_0
except: # noqa: E722
pass
return cast(Union[None, PayerTypeEnum, Unset], data)
payer_type = _parse_payer_type(d.pop("payer_type", UNSET))
delay = d.pop("delay", UNSET)
user_transaction = cls(
uuid=uuid,
payee_id=payee_id,
payee_type=payee_type,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
details=details,
role=role,
payer_id=payer_id,
payer_type=payer_type,
delay=delay,
)
user_transaction.additional_properties = d
return user_transaction
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

Binary file not shown.

View file

@ -0,0 +1,120 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-09 14:04+0330\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
#: apps/pg/constans.py:6
msgid "created"
msgstr ""
#: apps/pg/constans.py:7
msgid "ipg pending"
msgstr ""
#: apps/pg/constans.py:8
msgid "ipg success"
msgstr ""
#: apps/pg/constans.py:10
msgid "wallet submit pending"
msgstr ""
#: apps/pg/constans.py:11
msgid "wallet submit success"
msgstr ""
#: apps/pg/constans.py:13
msgid "failed"
msgstr ""
#: apps/pg/constans.py:14
msgid "expected failure"
msgstr ""
#: apps/pg/constans.py:15
msgid "success"
msgstr ""
#: apps/pg/constans.py:19
msgid "user"
msgstr ""
#: apps/pg/constans.py:20
msgid "application"
msgstr ""
#: apps/pg/models.py:24
msgid "fake"
msgstr ""
#: apps/pg/models.py:25
msgid "pna"
msgstr ""
#: apps/pg/models.py:133
msgid "charge via ipg"
msgstr ""
#: apps/users/models.py:49
msgid "password"
msgstr ""
#: apps/users/models.py:52
msgid "username"
msgstr ""
#: apps/users/models.py:55
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
msgstr ""
#: apps/users/models.py:58
msgid "A user with that username already exists."
msgstr ""
#: apps/users/models.py:64
msgid "last update"
msgstr ""
#: apps/users/models.py:65
msgid "last login"
msgstr ""
#: apps/users/models.py:66
msgid "date joined"
msgstr ""
#: main/settings.py:184
msgid "English"
msgstr ""
#: main/settings.py:185
msgid "Persian"
msgstr ""
#: main/settings.py:186
msgid "Arabic"
msgstr ""
#: main/settings.py:187
msgid "Turkish"
msgstr ""
#: templates/admin/input_filter.html:5
#, python-format
msgid " By %(filter_title)s "
msgstr ""

Binary file not shown.

View file

@ -0,0 +1,119 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-09 14:04+0330\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/pg/constans.py:6
msgid "created"
msgstr ""
#: apps/pg/constans.py:7
msgid "ipg pending"
msgstr ""
#: apps/pg/constans.py:8
msgid "ipg success"
msgstr ""
#: apps/pg/constans.py:10
msgid "wallet submit pending"
msgstr ""
#: apps/pg/constans.py:11
msgid "wallet submit success"
msgstr ""
#: apps/pg/constans.py:13
msgid "failed"
msgstr ""
#: apps/pg/constans.py:14
msgid "expected failure"
msgstr ""
#: apps/pg/constans.py:15
msgid "success"
msgstr ""
#: apps/pg/constans.py:19
msgid "user"
msgstr ""
#: apps/pg/constans.py:20
msgid "application"
msgstr ""
#: apps/pg/models.py:24
msgid "fake"
msgstr ""
#: apps/pg/models.py:25
msgid "pna"
msgstr ""
#: apps/pg/models.py:133
msgid "charge via ipg"
msgstr ""
#: apps/users/models.py:49
msgid "password"
msgstr ""
#: apps/users/models.py:52
msgid "username"
msgstr ""
#: apps/users/models.py:55
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
msgstr ""
#: apps/users/models.py:58
msgid "A user with that username already exists."
msgstr ""
#: apps/users/models.py:64
msgid "last update"
msgstr ""
#: apps/users/models.py:65
msgid "last login"
msgstr ""
#: apps/users/models.py:66
msgid "date joined"
msgstr ""
#: main/settings.py:184
msgid "English"
msgstr ""
#: main/settings.py:185
msgid "Persian"
msgstr ""
#: main/settings.py:186
msgid "Arabic"
msgstr ""
#: main/settings.py:187
msgid "Turkish"
msgstr ""
#: templates/admin/input_filter.html:5
#, python-format
msgid " By %(filter_title)s "
msgstr ""

Binary file not shown.

View file

@ -0,0 +1,119 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-09 14:03+0330\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: apps/pg/constans.py:6
msgid "created"
msgstr ""
#: apps/pg/constans.py:7
msgid "ipg pending"
msgstr ""
#: apps/pg/constans.py:8
msgid "ipg success"
msgstr ""
#: apps/pg/constans.py:10
msgid "wallet submit pending"
msgstr ""
#: apps/pg/constans.py:11
msgid "wallet submit success"
msgstr ""
#: apps/pg/constans.py:13
msgid "failed"
msgstr ""
#: apps/pg/constans.py:14
msgid "expected failure"
msgstr ""
#: apps/pg/constans.py:15
msgid "success"
msgstr ""
#: apps/pg/constans.py:19
msgid "user"
msgstr ""
#: apps/pg/constans.py:20
msgid "application"
msgstr ""
#: apps/pg/models.py:24
msgid "fake"
msgstr ""
#: apps/pg/models.py:25
msgid "pna"
msgstr ""
#: apps/pg/models.py:133
msgid "charge via ipg"
msgstr "افزایش موجودی از طریق پرداخت آنلاین"
#: apps/users/models.py:49
msgid "password"
msgstr ""
#: apps/users/models.py:52
msgid "username"
msgstr ""
#: apps/users/models.py:55
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
msgstr ""
#: apps/users/models.py:58
msgid "A user with that username already exists."
msgstr ""
#: apps/users/models.py:64
msgid "last update"
msgstr ""
#: apps/users/models.py:65
msgid "last login"
msgstr ""
#: apps/users/models.py:66
msgid "date joined"
msgstr ""
#: main/settings.py:184
msgid "English"
msgstr "انگلیسی"
#: main/settings.py:185
msgid "Persian"
msgstr "فارسی"
#: main/settings.py:186
msgid "Arabic"
msgstr "عربی"
#: main/settings.py:187
msgid "Turkish"
msgstr "ترکی"
#: templates/admin/input_filter.html:5
#, python-format
msgid " By %(filter_title)s "
msgstr ""

Binary file not shown.

View file

@ -0,0 +1,119 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-09 14:04+0330\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: apps/pg/constans.py:6
msgid "created"
msgstr ""
#: apps/pg/constans.py:7
msgid "ipg pending"
msgstr ""
#: apps/pg/constans.py:8
msgid "ipg success"
msgstr ""
#: apps/pg/constans.py:10
msgid "wallet submit pending"
msgstr ""
#: apps/pg/constans.py:11
msgid "wallet submit success"
msgstr ""
#: apps/pg/constans.py:13
msgid "failed"
msgstr ""
#: apps/pg/constans.py:14
msgid "expected failure"
msgstr ""
#: apps/pg/constans.py:15
msgid "success"
msgstr ""
#: apps/pg/constans.py:19
msgid "user"
msgstr ""
#: apps/pg/constans.py:20
msgid "application"
msgstr ""
#: apps/pg/models.py:24
msgid "fake"
msgstr ""
#: apps/pg/models.py:25
msgid "pna"
msgstr ""
#: apps/pg/models.py:133
msgid "charge via ipg"
msgstr ""
#: apps/users/models.py:49
msgid "password"
msgstr ""
#: apps/users/models.py:52
msgid "username"
msgstr ""
#: apps/users/models.py:55
msgid "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
msgstr ""
#: apps/users/models.py:58
msgid "A user with that username already exists."
msgstr ""
#: apps/users/models.py:64
msgid "last update"
msgstr ""
#: apps/users/models.py:65
msgid "last login"
msgstr ""
#: apps/users/models.py:66
msgid "date joined"
msgstr ""
#: main/settings.py:184
msgid "English"
msgstr ""
#: main/settings.py:185
msgid "Persian"
msgstr ""
#: main/settings.py:186
msgid "Arabic"
msgstr ""
#: main/settings.py:187
msgid "Turkish"
msgstr ""
#: templates/admin/input_filter.html:5
#, python-format
msgid " By %(filter_title)s "
msgstr ""

View file

@ -48,6 +48,7 @@ INSTALLED_APPS = [
'crispy_bootstrap5',
'django_filters',
'jalali_date',
'django_admin_logs',
# local apps
'apps.core',
@ -61,13 +62,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"
@ -76,12 +78,12 @@ OAUTH2_PROVIDER_ID_TOKEN_MODEL = "gooyal_oauth2.IDToken"
OAUTH2_PROVIDER_GRANT_MODEL = "gooyal_oauth2.Grant"
OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = "gooyal_oauth2.RefreshToken"
BASE_OAUTH2_PROVIDER_PUBLIC_URL = config("BASE_OAUTH2_PROVIDER_PUBLIC_URL")
BASE_OAUTH2_PROVIDER_PRIVATE_URL = config("BASE_OAUTH2_PROVIDER_PRIVATE_URL")
OAUTH2_PROVIDER_BASE_PUBLIC_URL = config("OAUTH2_PROVIDER_BASE_PUBLIC_URL")
OAUTH2_PROVIDER_BASE_PRIVATE_URL = config("OAUTH2_PROVIDER_BASE_PRIVATE_URL")
CLIENT_ID = config('CLIENT_ID')
CLIENT_SECRET = config('CLIENT_SECRET')
SCOPES = config('SCOPES', default='')
OAUTH2_PROVIDER_CLIENT_ID = config('OAUTH2_PROVIDER_CLIENT_ID')
OAUTH2_PROVIDER_CLIENT_SECRET = config('OAUTH2_PROVIDER_CLIENT_SECRET')
OAUTH2_PROVIDER_SCOPES = config('OAUTH2_PROVIDER_SCOPES', default='')
OAUTH2_PROVIDER = {
# this is the list of available scopes
# 'SCOPES_BACKEND_CLASS': 'apps.gooyal_oauth2.scopes.Scopes',
@ -90,22 +92,24 @@ OAUTH2_PROVIDER = {
# 'groups': 'Access to your groups',
# 'introspection': 'Introspect token scope'},
'OAUTH2_VALIDATOR_CLASS': 'apps.gooyal_oauth2.validators.OAuth2Validator',
'RESOURCE_SERVER_INTROSPECTION_URL': BASE_OAUTH2_PROVIDER_PRIVATE_URL + '/introspect/',
'RESOURCE_SERVER_INTROSPECTION_URL': OAUTH2_PROVIDER_BASE_PRIVATE_URL + '/introspect/',
# 'RESOURCE_SERVER_AUTH_TOKEN': '3yUqsWtwKYKHnfivFcJu', # OR this but not both:
'RESOURCE_SERVER_INTROSPECTION_CREDENTIALS': (CLIENT_ID, CLIENT_SECRET),
'RESOURCE_SERVER_INTROSPECTION_CREDENTIALS': (OAUTH2_PROVIDER_CLIENT_ID, OAUTH2_PROVIDER_CLIENT_SECRET),
}
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 200,
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
'EXCEPTION_HANDLER': 'utils.exceptions.exception_handler',
}
ROOT_URLCONF = 'main.urls'
@ -144,7 +148,6 @@ DATABASES = {
'HOST': config('DB_HOST', '127.0.0.1'),
'PORT': config('DB_PORT', ''),
}
}
# Password validation
@ -170,13 +173,20 @@ AUTH_PASSWORD_VALIDATORS = [
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Tehran'
USE_I18N = True
USE_L10N = True
USE_TZ = True
USE_TZ = False
LANGUAGES = [
('en', _('English')),
('fa', _('Persian')),
('ar', _('Arabic')),
('tr', _('Turkish')),
]
LOCALE_PATHS = [
BASE_DIR / 'locale',
@ -237,16 +247,61 @@ JALALI_DATE_DEFAULTS = {
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": config('BASE_REDIS_URL'),
"LOCATION": config('REDIS_BASE_URL'),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
PNA_CORPORATION_PIN = config('PNA_CORPORATION_PIN')
WALLET_BASE_PUBLIC_URL = config('WALLET_BASE_PUBLIC_URL')
IPG_BASE_PUBLIC_URL = config('IPG_BASE_PUBLIC_URL')
LOKI_BASE_PUBLIC_URL = config('LOKI_BASE_PUBLIC_URL', default=None, cast=str)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'loki': {
'class': 'utils.logs.LokiFormatter', # required
},
},
'handlers': {
'loki': {
'level': 'DEBUG', # Log level. Required
'class': 'utils.logs.LokiHandler', # Required
'formatter': 'loki', # Loki formatter. Required
'timeout': 2, # Post request timeout, default is 0.5. Optional
'url': f'{LOKI_BASE_PUBLIC_URL}/loki/api/v1/push', # Loki url. Defaults to localhost. Optional.
# 'auth': ("user", "password"), # Basic auth to authenticate with loki. Default is None (i.e. no auth). Optional
'tags': {"app": "ipg"}, # Tags / Labels to attach to the log. Optional, but strongly encoraged to use.
'mode': 'thread', # Push mode. Can be 'sync' or 'thread'. Sync is blocking, thread is non-blocking. Defaults to sync. Optional.
},
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
# 'formatter': 'verbose',
},
},
'loggers': {
'': {
'handlers': ['console', 'loki'],
'level': 'INFO',
'propagate': True,
},
},
}
PNA_CORPORATION_PIN = config('PNA_CORPORATION_PIN')
WALLET_BASE_PUBLIC_URL = config('WALLET_BASE_PUBLIC_URL')
WALLET_RIAL = config('WALLET_RIAL')
IPG_BASE_PUBLIC_URL = config('IPG_BASE_PUBLIC_URL')
COMMISSION_LEVEL1 = config('COMMISSION_LEVEL1', cast=int)
COMMISSION_LEVEL2_MIN_AMOUNT = config('COMMISSION_LEVEL2_MIN_AMOUNT', cast=int)
COMMISSION_LEVEL2_MAX_AMOUNT = config('COMMISSION_LEVEL2_MAX_AMOUNT', cast=int)
COMMISSION_LEVEL2_RATE = config('COMMISSION_LEVEL2_RATE', cast=float)
COMMISSION_LEVEL3 = config('COMMISSION_LEVEL3', cast=int)
SEP_TERMINAL_ID = config('SEP_TERMINAL_ID')
SEP_TERMINAL_PASSWORD = config('SEP_TERMINAL_PASSWORD')

View file

@ -16,4 +16,7 @@ django-oauth-toolkit
redis
celery
httpx
django-redis
django-redis
xlsxwriter
xlrd
django_admin_logs

View file

@ -1,5 +1,5 @@
#
# This file is autogenerated by pip-compile with Python 3.11
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile
@ -12,8 +12,6 @@ asgiref==3.8.1
# via
# django
# django-cors-headers
async-timeout==5.0.1
# via redis
attrs==24.3.0
# via
# jsonschema
@ -51,6 +49,7 @@ django==5.1.4
# via
# -r requirements.in
# crispy-bootstrap5
# django-admin-logs
# django-cors-headers
# django-crispy-forms
# django-filter
@ -59,6 +58,8 @@ django==5.1.4
# django-redis
# djangorestframework
# drf-spectacular
django-admin-logs==1.4.0
# via -r requirements.in
django-cors-headers==4.6.0
# via -r requirements.in
django-crispy-forms==2.3
@ -156,9 +157,7 @@ sqlparse==0.5.3
# via django
typing-extensions==4.12.2
# via
# anyio
# jwcrypto
# psycopg
# psycopg-pool
tzdata==2024.2
# via
@ -175,6 +174,10 @@ vine==5.1.0
# kombu
wcwidth==0.2.13
# via prompt-toolkit
xlrd==2.0.2
# via -r requirements.in
xlsxwriter==3.2.5
# via -r requirements.in
zope-event==5.0
# via gevent
zope-interface==7.2

View file

@ -0,0 +1,34 @@
.cursorily{ cursor: pointer;}
.hov:hover{ color: #000;}
.ico-size{font-size: 16px;}
.ico-size-month{font-size: 26px!important; line-height: 26px!important;}
.ico-size-large{ font-size: 40px!important; line-height: 30px;}
.dtp_main{ border: solid 1px #eee; border-radius: 3px; background-color: #fff; padding: 8px 0 8px 8px;}
.dtp_main span, .dtp_main i{ display: inline-block; padding-right: 8px;}
.dtp_modal-win{position: fixed;left: 0; top: 0; width: 100%; height: 100%;
z-index: 999; background-color: #eeeeee; opacity: 0.6;}
.dtp_modal-content{ background-color: #fff; border-radius: 10px; width: 624px;
position: absolute; z-index: 1000; top: 100px; left: 100px; font-size: 16px;font-weight: normal;}
.dtp_modal-content-no-time{ background-color: #fff; border-radius: 10px; width: 312px;
position: absolute; z-index: 1000; top: 100px; left: 100px; font-size: 16px;font-weight: normal;}
.dtp_modal-title{ border-bottom: solid 3px #54646b; padding: 16px 36px; margin-bottom: 16px; font-size: 22px; }
.dtp_modal-cell-date{ width: 312px; float: right; margin-bottom: 22px; margin-top: 6px;}
.dtp_modal-cell-time{width: 311px; float: left; direction: ltr; border-right: solid 1px #000;}
.dtp_modal-months{ color: #7d7d7d; text-align: center; font-size: 20px; padding: 0 20px;}
.dtp_modal-months span{ display: inline-block; padding: 10px 20px; width: 182px;}
.dtp_modal-calendar{ width: 266px; margin-left: 22px; }
.dtp_modal-calendar-cell{ width: 38px; padding: 7px 0; display: inline-block; text-align: center;}
.dtp_modal-colored{ color: #54646b; }
.dtp_modal-grey{ color: #7d7d7d; }
.dtp_modal-cell-selected{ background-color: #54646b; border-radius: 48%; transition: background-color 1s ease-out;}
.dtp_modal-time-block{ height: 212px; width: 310px; }
.dpt_modal-button{ background-color: #54646b; color: #fff; font-size: 24px; padding: 8px 40px; float: left;
text-align: center; display: inline-block; margin-left: 22px; cursor: pointer; border: solid 1px #fff;
border-radius: 3px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);}
.dtp_modal-time-line{ text-align: center; color: #7d7d7d; font-size: 20px; padding-top: 15px; }
.dtp_modal-time-mechanic{ padding-top: 16px;}
.dtp_modal-append{ color: #7d7d7d; padding-left: 108px; font-weight: normal; }
.dtp_modal-midle{ display: inline-block; width: 40px; }
.dtp_modal-midle-dig{display: inline-block; width: 16px; text-align: center; }
.dtp_modal-digits{ font-size: 50px; padding-left: 96px;}
.dtp_modal-digit{ }

BIN
static/image/pg/fail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
static/image/pg/tik.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

396
static/js/datetimepicker.js Normal file
View file

@ -0,0 +1,396 @@
(function ($) {
'use strict';
$.fn.dateTimePicker = function (options) {
var settings = $.extend({
selectData: "now",
dateFormat: "YYYY-MM-DD HH:mm",
showTime: true,
locale: 'en',
positionShift: { top: 20, left: 0},
title: "Select Date and Time",
buttonTitle: "Select",
allowBackwards: false
}, options);
moment.locale(settings.locale);
var elem = this;
var limitation = {"hour": 23, "minute": 59};
var mousedown = false;
var timeout = 800;
var selectDate = settings.selectData == "now" ? moment() : moment(settings.selectData, settings.dateFormat);
if (selectDate < moment() && (settings.allowBackwards == false)) {
selectDate = moment();
}
var startDate = copyDate(moment());
var lastSelected = copyDate(selectDate);
return this.each(function () {
if (lastSelected != selectDate) {
selectDate = copyDate(lastSelected);
}
elem.addClass("dtp_main");
updateMainElemGlobal();
// elem.text(selectDate.format(settings.dateFormat));
function updateMainElemGlobal() {
var arrF = settings.dateFormat.split(' ');
if (settings.showTime && arrF.length != 2) {
arrF.length = 2;
arrF[0] = 'DD/MM/YY';
arrF[1] = 'HH:mm';
}
var $s = $('<span>');
$s.text(lastSelected.format(arrF[0]));
elem.empty();
elem.append($s);
$s = $('<i>');
$s.addClass('fa fa-calendar ico-size');
elem.append($s);
if (settings.showTime) {
$s = $('<span>');
$s.text(lastSelected.format(arrF[1]));
elem.append($s);
$s = $('<i>');
$s.addClass('fa fa-clock-o ico-size');
elem.append($s);
}
}
elem.on('click', function () {
var $win = $('<div>');
$win.addClass("dtp_modal-win");
var $body = $('body');
$body.append($win);
var $content = createContent();
$body.append($content);
var offset = elem.offset();
$content.css({top: (offset.top + settings.positionShift.top) + "px", left: (offset.left + settings.positionShift.left) + "px"});
feelDates(selectDate);
$win.on('click', function () {
$content.remove();
$win.remove();
})
if (settings.showTime) {
attachChangeTime();
var $fieldTime = $('#field-time');
var $hour = $fieldTime.find('#d-hh');
var $minute = $fieldTime.find('#d-mm');
}
function feelDates(selectM) {
var $fDate = $content.find('#field-data');
$fDate.empty();
$fDate.append(createMonthPanel(selectM));
$fDate.append(createCalendar(selectM));
}
function createCalendar(selectedMonth) {
var $c = $('<div>');
$c.addClass('dtp_modal-calendar');
for (var i = 0; i < 7; i++) {
var $e = $('<div>');
$e.addClass('dtp_modal-calendar-cell dtp_modal-colored');
$e.text(moment().weekday(i).format('ddd'));
$c.append($e);
}
var m = copyDate(selectedMonth);
m.date(1);
// console.log(m.format('DD--MM--YYYY'));
// console.log(selectData.format('DD--MM--YYYY'));
// console.log(m.weekday());
var flagStart = totalMonths(selectedMonth) === totalMonths(startDate);
var flagSelect = totalMonths(lastSelected) === totalMonths(selectedMonth);
var cerDay = parseInt(selectedMonth.format('D'));
var dayNow = parseInt(startDate.format('D'));
for (var i = 0; i < 6; i++) {
for (var j = 0; j < 7; j++) {
var $b = $('<div>');
$b.html('&nbsp;');
$b.addClass('dtp_modal-calendar-cell');
if (m.month() == selectedMonth.month() && m.weekday() == j) {
var day = parseInt(m.format('D'));
$b.text(day);
if (flagStart && day < dayNow) {
if (settings.allowBackwards == false) {
$b.addClass('dtp_modal-grey');
} else {
$b.addClass('cursorily');
$b.bind('click', changeDate);
}
}
else if (flagSelect && day == cerDay) {
$b.addClass('dtp_modal-cell-selected');
}
else {
$b.addClass('cursorily');
$b.bind('click', changeDate);
}
m.add(1, 'days');
}
$c.append($b);
}
}
return $c;
}
function changeDate() {
var $div = $(this);
selectDate.date($div.text());
lastSelected = copyDate(selectDate);
updateDate();
var $fDate = $content.find('#field-data');
var old = $fDate.find('.dtp_modal-cell-selected');
old.removeClass('dtp_modal-cell-selected');
old.addClass('cursorily');
$div.addClass('dtp_modal-cell-selected');
$div.removeClass('cursorily');
old.bind('click', changeDate);
$div.unbind('click');
// console.log(selectDate.format('DD-MM-YYYY'));
}
function createMonthPanel(selectMonth) {
var $d = $('<div>');
$d.addClass('dtp_modal-months');
var $s = $('<i></i>');
$s.addClass('fa fa-angle-left cursorily ico-size-month hov');
//$s.attr('data-fa-mask', 'fas fa-circle');
$s.bind('click', prevMonth);
$d.append($s);
$s = $('<span>');
$s.text(selectMonth.format("MMMM YYYY"));
$d.append($s);
$s = $('<i></i>');
$s.addClass('fa fa-angle-right cursorily ico-size-month hov');
$s.bind('click', nextMonth);
$d.append($s);
return $d;
}
function close() {
if (settings.showTime) {
lastSelected.hour(parseInt($hour.text()));
lastSelected.minute(parseInt($minute.text()));
selectDate.hour(parseInt($hour.text()));
selectDate.minute(parseInt($minute.text()));
}
updateDate();
$content.remove();
$win.remove();
}
function nextMonth() {
selectDate.add(1, 'month');
feelDates(selectDate);
}
function prevMonth() {
if (totalMonths(selectDate) > totalMonths(startDate) || settings.allowBackwards == true) {
selectDate.add(-1, 'month');
feelDates(selectDate);
}
}
function attachChangeTime() {
var $angles = $($content).find('i[id^="angle-"]');
// $angles.bind('click', changeTime);
$angles.bind('mouseup', function () {
mousedown = false;
timeout = 800;
});
$angles.bind('mousedown', function () {
mousedown = true;
changeTime(this);
});
}
function changeTime(el) {
var $el = this || el;
$el = $($el);
///angle-up-hour angle-up-minute angle-down-hour angle-down-minute
var arr = $el.attr('id').split('-');
var increment = 1;
if (arr[1] == 'down') {
increment = -1;
}
appendIncrement(arr[2], increment);
setTimeout(function () {
autoIncrement($el);
}, timeout);
}
function autoIncrement(el) {
if (mousedown) {
if (timeout > 200) {
timeout -= 200;
}
changeTime(el);
}
}
function appendIncrement(typeDigits, increment) {
var $i = typeDigits == "hour" ? $hour : $minute;
var val = parseInt($i.text()) + increment;
if (val < 0) {
val = limitation[typeDigits];
}
else if (val > limitation[typeDigits]) {
val = 0;
}
$i.text(formatDigits(val));
}
function formatDigits(val) {
if (val < 10) {
return '0' + val;
}
return val;
}
function createTimer() {
var $div = $('<div>');
$div.addClass('dtp_modal-time-mechanic');
var $panel = $('<div>');
$panel.addClass('dtp_modal-append');
var $i = $('<i>');
$i.attr('id', 'angle-up-hour');
$i.addClass('fa fa-angle-up ico-size-large cursorily hov');
$panel.append($i);
var $m = $('<span>');
$m.addClass('dtp_modal-midle');
$panel.append($m);
$i = $('<i>');
$i.attr('id', 'angle-up-minute');
$i.addClass('fa fa-angle-up ico-size-large cursorily hov');
$panel.append($i);
$div.append($panel);
$panel = $('<div>');
$panel.addClass('dtp_modal-digits');
var $d = $('<span>');
$d.addClass('dtp_modal-digit');
$d.attr('id', 'd-hh');
$d.text(lastSelected.format('HH'));
$panel.append($d);
$m = $('<span>');
$m.addClass('dtp_modal-midle-dig');
$m.html(':');
$panel.append($m);
$d = $('<span>');
$d.addClass('dtp_modal-digit');
$d.attr('id', 'd-mm');
$d.text(lastSelected.format('mm'));
$panel.append($d);
$div.append($panel);
$panel = $('<div>');
$panel.addClass('dtp_modal-append');
$i = $('<i>');
$i.attr('id', 'angle-down-hour');
$i.addClass('fa fa-angle-down ico-size-large cursorily hov');
$panel.append($i);
$m = $('<span>');
$m.addClass('dtp_modal-midle');
$panel.append($m);
$i = $('<i>');
$i.attr('id', 'angle-down-minute');
$i.addClass('fa fa-angle-down ico-size-large cursorily hov');
$panel.append($i);
$div.append($panel);
return $div;
}
function createContent() {
var $c = $('<div>');
if (settings.showTime) {
$c.addClass("dtp_modal-content");
}
else {
$c.addClass("dtp_modal-content-no-time");
}
var $el = $('<div>');
$el.addClass("dtp_modal-title");
$el.text(settings.title);
$c.append($el);
$el = $('<div>');
$el.addClass('dtp_modal-cell-date');
$el.attr('id', 'field-data');
$c.append($el);
if (settings.showTime) {
$el = $('<div>');
$el.addClass('dtp_modal-cell-time');
var $a = $('<div>');
$a.addClass('dtp_modal-time-block');
$a.attr('id', 'field-time');
$el.append($a);
var $line = $('<div>');
$line.attr('id', 'time-line');
$line.addClass('dtp_modal-time-line');
$line.text(lastSelected.format(settings.dateFormat));
$a.append($line);
$a.append(createTimer());
var $but = $('<div>');
$but.addClass('dpt_modal-button');
$but.text(settings.buttonTitle);
$but.bind('click', close);
$el.append($but);
$c.append($el);
}
return $c;
}
function updateDate() {
if (settings.showTime) {
$('#time-line').text(lastSelected.format(settings.dateFormat));
}
updateMainElem();
elem.next().val(selectDate.format(settings.dateFormat));
if (!settings.showTime) {
$content.remove();
$win.remove();
}
}
function updateMainElem() {
var arrF = settings.dateFormat.split(' ');
if (settings.showTime && arrF.length != 2) {
arrF.length = 2;
arrF[0] = 'DD/MM/YY';
arrF[1] = 'HH:mm';
}
var $s = $('<span>');
$s.text(lastSelected.format(arrF[0]));
elem.empty();
elem.append($s);
$s = $('<i>');
$s.addClass('fa fa-calendar ico-size');
elem.append($s);
if (settings.showTime) {
$s = $('<span>');
$s.text(lastSelected.format(arrF[1]));
elem.append($s);
$s = $('<i>');
$s.addClass('fa fa-clock-o ico-size');
elem.append($s);
}
}
});
});
};
function copyDate(d) {
return moment(d.toDate());
}
function totalMonths(m) {
var r = m.format('YYYY') * 12 + parseInt(m.format('MM'));
return r;
}
}(jQuery));
// fa-caret-down

View file

@ -0,0 +1,15 @@
<!-- templates/admin/input_filter.html -->
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul>
<li>
<form method="GET" action="">
<input
type="text"
value="{{ spec.value|default_if_none:'' }}"
name="{{ spec.parameter_name }}"/>
</form>
</li>
</ul>

View file

@ -0,0 +1,11 @@
{% extends "admin/change_list.html" %}
{% load tags %}
{% block result_list %}
{{ block.super }}
<div style="margin-top: 20px; padding: 10px; background: #f8f8f8;">
<h3>جمع کل:</h3>
<p></p>
<p>{{ totals.total_amount|default:"0"|amount_split_3digit }}</p>
<p></p>
</div>
{% endblock %}

View file

@ -0,0 +1,168 @@
{% load static %}
{% load crispy_forms_tags %}
{% load jalali_tags %}
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment Unsuccessful</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
<style>
body {
margin: 0;
font-family: 'Vazirmatn', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.screen-content {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.message-section {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
}
.error-icon {
width: 40px;
height: 40px;
background-color: #e53935; /* Red for error */
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 24px;
font-weight: bold;
}
.error-text {
color: #e53935;
font-size: 1.1rem;
font-weight: bold;
margin-top: 15px;
margin-bottom: 25px;
}
.divider {
width: 100%;
height: 1px;
background-color: #eeeeee;
border: none;
margin-bottom: 25px;
}
.details-text {
color: #757575;
font-size: 0.9rem;
line-height: 1.6;
}
.details-text .code {
color: #424242;
font-weight: 600;
}
.placeholder-link {
color: #bdbdbd;
font-size: 0.9rem;
text-decoration: underline;
margin-top: 40px;
}
.button-container {
display: flex;
flex-direction: column;
gap: 15px;
width: 100%;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
width: 100%;
padding: 14px;
border-radius: 8px;
font-size: 1rem;
font-weight: bold;
font-family: 'Vazirmatn', sans-serif;
cursor: pointer;
transition: all 0.2s ease-in-out;
border: 1px solid transparent;
}
.btn-retry {
background-color: #ffffff;
border: 2px solid #6931c9;
color: #6931c9;
}
.btn-retry:hover {
background-color: #f9f7fd;
}
.btn-primary {
background-color: #3B604B;
color: #ffffff;
}
.btn-primary:hover {
background-color: #3B604B;
}
</style>
</head>
<body>
<div class="mobile-frame">
<div class="screen-content">
<div class="message-section">
<div ><img src="{% static "image/pg/fail.png" %}" alt="fail"></div>
{% if message %}
<p class="error-text">{{ message }}</p>
{% else %}
<p class="error-text">پرداخت ناموفق </p>
{% endif %}
<hr class="divider">
<div class="details-text">
<p>کد پیگیری تراکنش شما: <span class="code">{{ object.reference_number }}</span></p>
<p>در صورت کسر از موجودی، مبلغ پرداختی طی یک تا 72 ساعت آینده به حساب شما بازگردانده خواهد شد.</p>
</div>
<a href="https://winsoo.ir" class="placeholder-link">winsoo</a>
</div>
<div class="button-container">
<form action="{{ request.get_full_path }}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" name="redirect-to-app" value="true">بازگشت به صفحه اصلی</button>
</form>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,162 @@
{% load static %}
{% load crispy_forms_tags %}
{% load jalali_tags %}
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payment Successful</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap" rel="stylesheet">
<style>
body {
margin: 0;
font-family: 'Vazirmatn', sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.screen-content {
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.message-section {
width: 100%;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
}
.success-icon {
width: 50px;
height: 50px;
background-color: #4CAF50;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 28px;
font-weight: bold;
}
.title {
color: #333;
font-size: 1.2rem;
font-weight: bold;
margin-top: 20px;
margin-bottom: 8px;
}
.subtitle {
color: #757575;
font-size: 0.9rem;
margin-bottom: 25px;
}
.divider {
width: 100%;
height: 1px;
background-color: #eeeeee;
border: none;
margin-bottom: 25px;
}
.amount-row {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1rem;
}
.amount-label {
color: #757575;
}
.amount-value {
color: #4CAF50;
font-weight: bold;
}
.placeholder-link {
color: #bdbdbd;
font-size: 0.9rem;
text-decoration: underline;
margin-top: 100px;
}
.button-container {
width: 100%;
display: flex;
flex-direction: column;
}
.btn {
width: 100%;
padding: 15px;
border: none;
border-radius: 8px;
font-size: 1.1rem;
font-weight: bold;
font-family: 'Vazirmatn', sans-serif;
cursor: pointer;
transition: all 0.2s ease-in-out;
}
.btn-primary {
background-color: #3B604B;
color: #ffffff;
}
.btn-primary:hover {
background-color: #3B604B;
}
</style>
</head>
<body>
<div class="mobile-frame">
<div class="screen-content">
<div class="message-section">
<div ><img src="{% static "image/pg/tik.png" %}" alt="success"></div>
<p class="title">پرداخت موفق</p>
<hr class="divider">
<div class="amount-row">
<span class="amount-label">مبلغ شارژ</span>
<span class="amount-value">{{ object.amount }} ریال</span>
</div>
<a href="https://winsoo.ir" class="placeholder-link">winsoo</a>
</div>
<div class="button-container">
<form action="{{ request.get_full_path }}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" name="redirect-to-app" value="true">بازگشت به وینسو</button>
</form>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
"""Contains endpoint functions for accessing the API"""

View file

@ -10,6 +10,7 @@ from ...types import Response
def _get_kwargs(
payer_wallet: str,
*,
body: ApplicationDeposit,
) -> dict[str, Any]:
@ -17,12 +18,11 @@ def _get_kwargs(
_kwargs: dict[str, Any] = {
"method": "post",
"url": "/wallet/api/application/deposit/",
"url": f"/wallet/api/application/{payer_wallet}/deposit/",
}
_body = body.to_dict()
_kwargs["json"] = body.to_dict()
_kwargs["json"] = _body
headers["Content-Type"] = "application/json"
_kwargs["headers"] = headers
@ -36,6 +36,7 @@ def _parse_response(
response_201 = ApplicationDeposit.from_dict(response.json())
return response_201
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
@ -54,12 +55,14 @@ def _build_response(
def sync_detailed(
payer_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationDeposit,
) -> Response[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
body (ApplicationDeposit):
Raises:
@ -71,6 +74,7 @@ def sync_detailed(
"""
kwargs = _get_kwargs(
payer_wallet=payer_wallet,
body=body,
)
@ -82,12 +86,14 @@ def sync_detailed(
def sync(
payer_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationDeposit,
) -> Optional[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
body (ApplicationDeposit):
Raises:
@ -99,18 +105,21 @@ def sync(
"""
return sync_detailed(
payer_wallet=payer_wallet,
client=client,
body=body,
).parsed
async def asyncio_detailed(
payer_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationDeposit,
) -> Response[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
body (ApplicationDeposit):
Raises:
@ -122,6 +131,7 @@ async def asyncio_detailed(
"""
kwargs = _get_kwargs(
payer_wallet=payer_wallet,
body=body,
)
@ -131,12 +141,14 @@ async def asyncio_detailed(
async def asyncio(
payer_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationDeposit,
) -> Optional[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
body (ApplicationDeposit):
Raises:
@ -149,6 +161,7 @@ async def asyncio(
return (
await asyncio_detailed(
payer_wallet=payer_wallet,
client=client,
body=body,
)

View file

@ -10,11 +10,12 @@ from ...types import Response
def _get_kwargs(
payer_wallet: str,
uuid: str,
) -> dict[str, Any]:
_kwargs: dict[str, Any] = {
"method": "get",
"url": f"/wallet/api/application/deposit/{uuid}/verify",
"url": f"/wallet/api/application/{payer_wallet}/deposit/{uuid}/verify",
}
return _kwargs
@ -27,6 +28,7 @@ def _parse_response(
response_200 = ApplicationDeposit.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
@ -45,12 +47,14 @@ def _build_response(
def sync_detailed(
payer_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Response[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
uuid (str):
Raises:
@ -62,6 +66,7 @@ def sync_detailed(
"""
kwargs = _get_kwargs(
payer_wallet=payer_wallet,
uuid=uuid,
)
@ -73,12 +78,14 @@ def sync_detailed(
def sync(
payer_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Optional[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
uuid (str):
Raises:
@ -90,18 +97,21 @@ def sync(
"""
return sync_detailed(
payer_wallet=payer_wallet,
uuid=uuid,
client=client,
).parsed
async def asyncio_detailed(
payer_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Response[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
uuid (str):
Raises:
@ -113,6 +123,7 @@ async def asyncio_detailed(
"""
kwargs = _get_kwargs(
payer_wallet=payer_wallet,
uuid=uuid,
)
@ -122,12 +133,14 @@ async def asyncio_detailed(
async def asyncio(
payer_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Optional[ApplicationDeposit]:
"""
Args:
payer_wallet (str):
uuid (str):
Raises:
@ -140,6 +153,7 @@ async def asyncio(
return (
await asyncio_detailed(
payer_wallet=payer_wallet,
uuid=uuid,
client=client,
)

View file

@ -0,0 +1,227 @@
from http import HTTPStatus
from typing import Any, Optional, Union
from uuid import UUID
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.paginated_transaction_list import PaginatedTransactionList
from ...types import UNSET, Response, Unset
def _get_kwargs(
*,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> dict[str, Any]:
params: dict[str, Any] = {}
params["limit"] = limit
params["offset"] = offset
json_payee: Union[Unset, str] = UNSET
if not isinstance(payee, Unset):
json_payee = str(payee)
params["payee"] = json_payee
json_payer: Union[Unset, str] = UNSET
if not isinstance(payer, Unset):
json_payer = str(payer)
params["payer"] = json_payer
json_wallets = []
for wallets_item_data in wallets:
wallets_item = str(wallets_item_data)
json_wallets.append(wallets_item)
params["wallets"] = json_wallets
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/wallet/api/application/transactions/",
"params": params,
}
return _kwargs
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[PaginatedTransactionList]:
if response.status_code == 200:
response_200 = PaginatedTransactionList.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[PaginatedTransactionList]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)
def sync_detailed(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Response[PaginatedTransactionList]:
"""
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedTransactionList]
"""
kwargs = _get_kwargs(
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
)
response = client.get_httpx_client().request(
**kwargs,
)
return _build_response(client=client, response=response)
def sync(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Optional[PaginatedTransactionList]:
"""
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedTransactionList
"""
return sync_detailed(
client=client,
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Response[PaginatedTransactionList]:
"""
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedTransactionList]
"""
kwargs = _get_kwargs(
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
)
response = await client.get_async_httpx_client().request(**kwargs)
return _build_response(client=client, response=response)
async def asyncio(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Optional[PaginatedTransactionList]:
"""
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedTransactionList
"""
return (
await asyncio_detailed(
client=client,
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
)
).parsed

View file

@ -1,41 +1,39 @@
from http import HTTPStatus
from typing import Any, Optional, Union
from uuid import UUID
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.application_transaction import ApplicationTransaction
from ...models.transaction import Transaction
from ...types import Response
def _get_kwargs(
uuid: str,
uuid: UUID,
) -> dict[str, Any]:
_kwargs: dict[str, Any] = {
"method": "get",
"url": f"/wallet/api/application/{uuid}/",
"url": f"/wallet/api/application/transactions/{uuid}/",
}
return _kwargs
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[ApplicationTransaction]:
def _parse_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Optional[Transaction]:
if response.status_code == 200:
response_200 = ApplicationTransaction.from_dict(response.json())
response_200 = Transaction.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[ApplicationTransaction]:
def _build_response(*, client: Union[AuthenticatedClient, Client], response: httpx.Response) -> Response[Transaction]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
@ -45,20 +43,20 @@ def _build_response(
def sync_detailed(
uuid: str,
uuid: UUID,
*,
client: AuthenticatedClient,
) -> Response[ApplicationTransaction]:
) -> Response[Transaction]:
"""
Args:
uuid (str):
uuid (UUID):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[ApplicationTransaction]
Response[Transaction]
"""
kwargs = _get_kwargs(
@ -73,20 +71,20 @@ def sync_detailed(
def sync(
uuid: str,
uuid: UUID,
*,
client: AuthenticatedClient,
) -> Optional[ApplicationTransaction]:
) -> Optional[Transaction]:
"""
Args:
uuid (str):
uuid (UUID):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
ApplicationTransaction
Transaction
"""
return sync_detailed(
@ -96,20 +94,20 @@ def sync(
async def asyncio_detailed(
uuid: str,
uuid: UUID,
*,
client: AuthenticatedClient,
) -> Response[ApplicationTransaction]:
) -> Response[Transaction]:
"""
Args:
uuid (str):
uuid (UUID):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[ApplicationTransaction]
Response[Transaction]
"""
kwargs = _get_kwargs(
@ -122,20 +120,20 @@ async def asyncio_detailed(
async def asyncio(
uuid: str,
uuid: UUID,
*,
client: AuthenticatedClient,
) -> Optional[ApplicationTransaction]:
) -> Optional[Transaction]:
"""
Args:
uuid (str):
uuid (UUID):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
ApplicationTransaction
Transaction
"""
return (

View file

@ -0,0 +1,208 @@
from http import HTTPStatus
from typing import Any, Optional, Union
from uuid import UUID
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.paginated_account_list import PaginatedAccountList
from ...types import UNSET, Response, Unset
def _get_kwargs(
owner: str,
*,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> dict[str, Any]:
params: dict[str, Any] = {}
params["limit"] = limit
params["offset"] = offset
json_wallet = []
for wallet_item_data in wallet:
wallet_item = str(wallet_item_data)
json_wallet.append(wallet_item)
params["wallet"] = json_wallet
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
_kwargs: dict[str, Any] = {
"method": "get",
"url": f"/wallet/api/application/user/wallets/{owner}/",
"params": params,
}
return _kwargs
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[PaginatedAccountList]:
if response.status_code == 200:
response_200 = PaginatedAccountList.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[PaginatedAccountList]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)
def sync_detailed(
owner: str,
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Response[PaginatedAccountList]:
"""API for getting specified user wallet.
Args:
owner (str):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedAccountList]
"""
kwargs = _get_kwargs(
owner=owner,
limit=limit,
offset=offset,
wallet=wallet,
)
response = client.get_httpx_client().request(
**kwargs,
)
return _build_response(client=client, response=response)
def sync(
owner: str,
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Optional[PaginatedAccountList]:
"""API for getting specified user wallet.
Args:
owner (str):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedAccountList
"""
return sync_detailed(
owner=owner,
client=client,
limit=limit,
offset=offset,
wallet=wallet,
).parsed
async def asyncio_detailed(
owner: str,
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Response[PaginatedAccountList]:
"""API for getting specified user wallet.
Args:
owner (str):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedAccountList]
"""
kwargs = _get_kwargs(
owner=owner,
limit=limit,
offset=offset,
wallet=wallet,
)
response = await client.get_async_httpx_client().request(**kwargs)
return _build_response(client=client, response=response)
async def asyncio(
owner: str,
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Optional[PaginatedAccountList]:
"""API for getting specified user wallet.
Args:
owner (str):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedAccountList
"""
return (
await asyncio_detailed(
owner=owner,
client=client,
limit=limit,
offset=offset,
wallet=wallet,
)
).parsed

View file

@ -5,23 +5,26 @@ import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.paginated_application_transaction_list import PaginatedApplicationTransactionList
from ...models.paginated_account_list import PaginatedAccountList
from ...types import UNSET, Response, Unset
def _get_kwargs(
*,
page: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
) -> dict[str, Any]:
params: dict[str, Any] = {}
params["page"] = page
params["limit"] = limit
params["offset"] = offset
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/wallet/api/application/",
"url": "/wallet/api/application/wallets/",
"params": params,
}
@ -30,11 +33,12 @@ def _get_kwargs(
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[PaginatedApplicationTransactionList]:
) -> Optional[PaginatedAccountList]:
if response.status_code == 200:
response_200 = PaginatedApplicationTransactionList.from_dict(response.json())
response_200 = PaginatedAccountList.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
@ -43,7 +47,7 @@ def _parse_response(
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[PaginatedApplicationTransactionList]:
) -> Response[PaginatedAccountList]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
@ -55,22 +59,26 @@ def _build_response(
def sync_detailed(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Response[PaginatedApplicationTransactionList]:
"""
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
) -> Response[PaginatedAccountList]:
"""API for getting specified user or application balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedApplicationTransactionList]
Response[PaginatedAccountList]
"""
kwargs = _get_kwargs(
page=page,
limit=limit,
offset=offset,
)
response = client.get_httpx_client().request(
@ -83,45 +91,53 @@ def sync_detailed(
def sync(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Optional[PaginatedApplicationTransactionList]:
"""
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
) -> Optional[PaginatedAccountList]:
"""API for getting specified user or application balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedApplicationTransactionList
PaginatedAccountList
"""
return sync_detailed(
client=client,
page=page,
limit=limit,
offset=offset,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Response[PaginatedApplicationTransactionList]:
"""
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
) -> Response[PaginatedAccountList]:
"""API for getting specified user or application balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedApplicationTransactionList]
Response[PaginatedAccountList]
"""
kwargs = _get_kwargs(
page=page,
limit=limit,
offset=offset,
)
response = await client.get_async_httpx_client().request(**kwargs)
@ -132,23 +148,27 @@ async def asyncio_detailed(
async def asyncio(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Optional[PaginatedApplicationTransactionList]:
"""
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
) -> Optional[PaginatedAccountList]:
"""API for getting specified user or application balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedApplicationTransactionList
PaginatedAccountList
"""
return (
await asyncio_detailed(
client=client,
page=page,
limit=limit,
offset=offset,
)
).parsed

View file

@ -10,6 +10,7 @@ from ...types import Response
def _get_kwargs(
payee_wallet: str,
*,
body: ApplicationWithdraw,
) -> dict[str, Any]:
@ -17,12 +18,11 @@ def _get_kwargs(
_kwargs: dict[str, Any] = {
"method": "post",
"url": "/wallet/api/application/withdraw/",
"url": f"/wallet/api/application/{payee_wallet}/withdraw/",
}
_body = body.to_dict()
_kwargs["json"] = body.to_dict()
_kwargs["json"] = _body
headers["Content-Type"] = "application/json"
_kwargs["headers"] = headers
@ -36,6 +36,7 @@ def _parse_response(
response_201 = ApplicationWithdraw.from_dict(response.json())
return response_201
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
@ -54,12 +55,14 @@ def _build_response(
def sync_detailed(
payee_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationWithdraw,
) -> Response[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
body (ApplicationWithdraw):
Raises:
@ -71,6 +74,7 @@ def sync_detailed(
"""
kwargs = _get_kwargs(
payee_wallet=payee_wallet,
body=body,
)
@ -82,12 +86,14 @@ def sync_detailed(
def sync(
payee_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationWithdraw,
) -> Optional[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
body (ApplicationWithdraw):
Raises:
@ -99,18 +105,21 @@ def sync(
"""
return sync_detailed(
payee_wallet=payee_wallet,
client=client,
body=body,
).parsed
async def asyncio_detailed(
payee_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationWithdraw,
) -> Response[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
body (ApplicationWithdraw):
Raises:
@ -122,6 +131,7 @@ async def asyncio_detailed(
"""
kwargs = _get_kwargs(
payee_wallet=payee_wallet,
body=body,
)
@ -131,12 +141,14 @@ async def asyncio_detailed(
async def asyncio(
payee_wallet: str,
*,
client: AuthenticatedClient,
body: ApplicationWithdraw,
) -> Optional[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
body (ApplicationWithdraw):
Raises:
@ -149,6 +161,7 @@ async def asyncio(
return (
await asyncio_detailed(
payee_wallet=payee_wallet,
client=client,
body=body,
)

View file

@ -10,11 +10,12 @@ from ...types import Response
def _get_kwargs(
payee_wallet: str,
uuid: str,
) -> dict[str, Any]:
_kwargs: dict[str, Any] = {
"method": "get",
"url": f"/wallet/api/application/withdraw/{uuid}/verify",
"url": f"/wallet/api/application/{payee_wallet}/withdraw/{uuid}/verify",
}
return _kwargs
@ -27,6 +28,7 @@ def _parse_response(
response_200 = ApplicationWithdraw.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
@ -45,12 +47,14 @@ def _build_response(
def sync_detailed(
payee_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Response[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
uuid (str):
Raises:
@ -62,6 +66,7 @@ def sync_detailed(
"""
kwargs = _get_kwargs(
payee_wallet=payee_wallet,
uuid=uuid,
)
@ -73,12 +78,14 @@ def sync_detailed(
def sync(
payee_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Optional[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
uuid (str):
Raises:
@ -90,18 +97,21 @@ def sync(
"""
return sync_detailed(
payee_wallet=payee_wallet,
uuid=uuid,
client=client,
).parsed
async def asyncio_detailed(
payee_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Response[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
uuid (str):
Raises:
@ -113,6 +123,7 @@ async def asyncio_detailed(
"""
kwargs = _get_kwargs(
payee_wallet=payee_wallet,
uuid=uuid,
)
@ -122,12 +133,14 @@ async def asyncio_detailed(
async def asyncio(
payee_wallet: str,
uuid: str,
*,
client: AuthenticatedClient,
) -> Optional[ApplicationWithdraw]:
"""
Args:
payee_wallet (str):
uuid (str):
Raises:
@ -140,6 +153,7 @@ async def asyncio(
return (
await asyncio_detailed(
payee_wallet=payee_wallet,
uuid=uuid,
client=client,
)

View file

@ -0,0 +1,247 @@
from http import HTTPStatus
from typing import Any, Optional, Union
from uuid import UUID
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.paginated_transaction_list import PaginatedTransactionList
from ...types import UNSET, Response, Unset
def _get_kwargs(
*,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> dict[str, Any]:
params: dict[str, Any] = {}
params["limit"] = limit
params["offset"] = offset
json_payee: Union[Unset, str] = UNSET
if not isinstance(payee, Unset):
json_payee = str(payee)
params["payee"] = json_payee
json_payer: Union[Unset, str] = UNSET
if not isinstance(payer, Unset):
json_payer = str(payer)
params["payer"] = json_payer
json_wallets = []
for wallets_item_data in wallets:
wallets_item = str(wallets_item_data)
json_wallets.append(wallets_item)
params["wallets"] = json_wallets
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/wallet/api/transactions/",
"params": params,
}
return _kwargs
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[PaginatedTransactionList]:
if response.status_code == 200:
response_200 = PaginatedTransactionList.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
return None
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[PaginatedTransactionList]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
headers=response.headers,
parsed=_parse_response(client=client, response=response),
)
def sync_detailed(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Response[PaginatedTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedTransactionList]
"""
kwargs = _get_kwargs(
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
)
response = client.get_httpx_client().request(
**kwargs,
)
return _build_response(client=client, response=response)
def sync(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Optional[PaginatedTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedTransactionList
"""
return sync_detailed(
client=client,
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Response[PaginatedTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedTransactionList]
"""
kwargs = _get_kwargs(
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
)
response = await client.get_async_httpx_client().request(**kwargs)
return _build_response(client=client, response=response)
async def asyncio(
*,
client: AuthenticatedClient,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
payee: Union[Unset, UUID] = UNSET,
payer: Union[Unset, UUID] = UNSET,
wallets: list[UUID],
) -> Optional[PaginatedTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
Args:
limit (Union[Unset, int]):
offset (Union[Unset, int]):
payee (Union[Unset, UUID]):
payer (Union[Unset, UUID]):
wallets (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedTransactionList
"""
return (
await asyncio_detailed(
client=client,
limit=limit,
offset=offset,
payee=payee,
payer=payer,
wallets=wallets,
)
).parsed

View file

@ -1,27 +1,39 @@
from http import HTTPStatus
from typing import Any, Optional, Union
from uuid import UUID
import httpx
from ... import errors
from ...client import AuthenticatedClient, Client
from ...models.paginated_user_transaction_list import PaginatedUserTransactionList
from ...models.paginated_account_list import PaginatedAccountList
from ...types import UNSET, Response, Unset
def _get_kwargs(
*,
page: Union[Unset, int] = UNSET,
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> dict[str, Any]:
params: dict[str, Any] = {}
params["page"] = page
params["limit"] = limit
params["offset"] = offset
json_wallet = []
for wallet_item_data in wallet:
wallet_item = str(wallet_item_data)
json_wallet.append(wallet_item)
params["wallet"] = json_wallet
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/wallet/api/transactions/",
"url": "/wallet/api/wallets/",
"params": params,
}
@ -30,11 +42,12 @@ def _get_kwargs(
def _parse_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Optional[PaginatedUserTransactionList]:
) -> Optional[PaginatedAccountList]:
if response.status_code == 200:
response_200 = PaginatedUserTransactionList.from_dict(response.json())
response_200 = PaginatedAccountList.from_dict(response.json())
return response_200
if client.raise_on_unexpected_status:
raise errors.UnexpectedStatus(response.status_code, response.content)
else:
@ -43,7 +56,7 @@ def _parse_response(
def _build_response(
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
) -> Response[PaginatedUserTransactionList]:
) -> Response[PaginatedAccountList]:
return Response(
status_code=HTTPStatus(response.status_code),
content=response.content,
@ -55,27 +68,29 @@ def _build_response(
def sync_detailed(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Response[PaginatedUserTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Response[PaginatedAccountList]:
"""API for getting authenticated user balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedUserTransactionList]
Response[PaginatedAccountList]
"""
kwargs = _get_kwargs(
page=page,
limit=limit,
offset=offset,
wallet=wallet,
)
response = client.get_httpx_client().request(
@ -88,55 +103,59 @@ def sync_detailed(
def sync(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Optional[PaginatedUserTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Optional[PaginatedAccountList]:
"""API for getting authenticated user balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedUserTransactionList
PaginatedAccountList
"""
return sync_detailed(
client=client,
page=page,
limit=limit,
offset=offset,
wallet=wallet,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Response[PaginatedUserTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Response[PaginatedAccountList]:
"""API for getting authenticated user balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
Response[PaginatedUserTransactionList]
Response[PaginatedAccountList]
"""
kwargs = _get_kwargs(
page=page,
limit=limit,
offset=offset,
wallet=wallet,
)
response = await client.get_async_httpx_client().request(**kwargs)
@ -147,28 +166,30 @@ async def asyncio_detailed(
async def asyncio(
*,
client: AuthenticatedClient,
page: Union[Unset, int] = UNSET,
) -> Optional[PaginatedUserTransactionList]:
"""GET: API for getting list of transactions for authenticated user
POST: API for creating transaction for transferring funds from authenticated user to application
owner. (deprecated)
args:
- user: authenticated user
limit: Union[Unset, int] = UNSET,
offset: Union[Unset, int] = UNSET,
wallet: list[UUID],
) -> Optional[PaginatedAccountList]:
"""API for getting authenticated user balance.
Args:
page (Union[Unset, int]):
limit (Union[Unset, int]):
offset (Union[Unset, int]):
wallet (list[UUID]):
Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
httpx.TimeoutException: If the request takes longer than Client.timeout.
Returns:
PaginatedUserTransactionList
PaginatedAccountList
"""
return (
await asyncio_detailed(
client=client,
page=page,
limit=limit,
offset=offset,
wallet=wallet,
)
).parsed

View file

@ -0,0 +1,19 @@
"""Contains all the data models used in inputs/outputs"""
from .account import Account
from .application_deposit import ApplicationDeposit
from .application_withdraw import ApplicationWithdraw
from .paginated_account_list import PaginatedAccountList
from .paginated_transaction_list import PaginatedTransactionList
from .state_enum import StateEnum
from .transaction import Transaction
__all__ = (
"Account",
"ApplicationDeposit",
"ApplicationWithdraw",
"PaginatedAccountList",
"PaginatedTransactionList",
"StateEnum",
"Transaction",
)

View file

@ -0,0 +1,90 @@
from collections.abc import Mapping
from typing import Any, TypeVar, Union, cast
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from ..types import UNSET, Unset
T = TypeVar("T", bound="Account")
@_attrs_define
class Account:
"""
Attributes:
balance (Union[Unset, int]):
wallet (Union[None, UUID, Unset]):
"""
balance: Union[Unset, int] = UNSET
wallet: Union[None, UUID, Unset] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
balance = self.balance
wallet: Union[None, Unset, str]
if isinstance(self.wallet, Unset):
wallet = UNSET
elif isinstance(self.wallet, UUID):
wallet = str(self.wallet)
else:
wallet = self.wallet
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if balance is not UNSET:
field_dict["balance"] = balance
if wallet is not UNSET:
field_dict["wallet"] = wallet
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
balance = d.pop("balance", UNSET)
def _parse_wallet(data: object) -> Union[None, UUID, Unset]:
if data is None:
return data
if isinstance(data, Unset):
return data
try:
if not isinstance(data, str):
raise TypeError()
wallet_type_0 = UUID(data)
return wallet_type_0
except: # noqa: E722
pass
return cast(Union[None, UUID, Unset], data)
wallet = _parse_wallet(d.pop("wallet", UNSET))
account = cls(
balance=balance,
wallet=wallet,
)
account.additional_properties = d
return account
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -0,0 +1,168 @@
import datetime
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="ApplicationDeposit")
@_attrs_define
class ApplicationDeposit:
"""
Attributes:
payer (str):
payer_type (str):
payer_wallet (UUID):
payee (UUID):
payee_type (int):
payee_wallet (UUID):
created_at (datetime.datetime):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (datetime.datetime):
uuid (Union[Unset, UUID]):
details (Union[Unset, Any]):
"""
payer: str
payer_type: str
payer_wallet: UUID
payee: UUID
payee_type: int
payee_wallet: UUID
created_at: datetime.datetime
state: StateEnum
amount: int
updated_at: datetime.datetime
uuid: Union[Unset, UUID] = UNSET
details: Union[Unset, Any] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
payer = self.payer
payer_type = self.payer_type
payer_wallet = str(self.payer_wallet)
payee = str(self.payee)
payee_type = self.payee_type
payee_wallet = str(self.payee_wallet)
created_at = self.created_at.isoformat()
state = self.state.value
amount = self.amount
updated_at = self.updated_at.isoformat()
uuid: Union[Unset, str] = UNSET
if not isinstance(self.uuid, Unset):
uuid = str(self.uuid)
details = self.details
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"payer": payer,
"payer_type": payer_type,
"payer_wallet": payer_wallet,
"payee": payee,
"payee_type": payee_type,
"payee_wallet": payee_wallet,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
}
)
if uuid is not UNSET:
field_dict["uuid"] = uuid
if details is not UNSET:
field_dict["details"] = details
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
payer = d.pop("payer")
payer_type = d.pop("payer_type")
payer_wallet = UUID(d.pop("payer_wallet"))
payee = UUID(d.pop("payee"))
payee_type = d.pop("payee_type")
payee_wallet = UUID(d.pop("payee_wallet"))
created_at = isoparse(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
updated_at = isoparse(d.pop("updated_at"))
_uuid = d.pop("uuid", UNSET)
uuid: Union[Unset, UUID]
if isinstance(_uuid, Unset):
uuid = UNSET
else:
uuid = UUID(_uuid)
details = d.pop("details", UNSET)
application_deposit = cls(
payer=payer,
payer_type=payer_type,
payer_wallet=payer_wallet,
payee=payee,
payee_type=payee_type,
payee_wallet=payee_wallet,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
uuid=uuid,
details=details,
)
application_deposit.additional_properties = d
return application_deposit
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -0,0 +1,168 @@
import datetime
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="ApplicationWithdraw")
@_attrs_define
class ApplicationWithdraw:
"""
Attributes:
payer (UUID):
payer_type (int):
payer_wallet (UUID):
payee (str):
payee_type (str):
payee_wallet (UUID):
created_at (datetime.datetime):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (datetime.datetime):
uuid (Union[Unset, UUID]):
details (Union[Unset, Any]):
"""
payer: UUID
payer_type: int
payer_wallet: UUID
payee: str
payee_type: str
payee_wallet: UUID
created_at: datetime.datetime
state: StateEnum
amount: int
updated_at: datetime.datetime
uuid: Union[Unset, UUID] = UNSET
details: Union[Unset, Any] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
payer = str(self.payer)
payer_type = self.payer_type
payer_wallet = str(self.payer_wallet)
payee = self.payee
payee_type = self.payee_type
payee_wallet = str(self.payee_wallet)
created_at = self.created_at.isoformat()
state = self.state.value
amount = self.amount
updated_at = self.updated_at.isoformat()
uuid: Union[Unset, str] = UNSET
if not isinstance(self.uuid, Unset):
uuid = str(self.uuid)
details = self.details
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"payer": payer,
"payer_type": payer_type,
"payer_wallet": payer_wallet,
"payee": payee,
"payee_type": payee_type,
"payee_wallet": payee_wallet,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
}
)
if uuid is not UNSET:
field_dict["uuid"] = uuid
if details is not UNSET:
field_dict["details"] = details
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
payer = UUID(d.pop("payer"))
payer_type = d.pop("payer_type")
payer_wallet = UUID(d.pop("payer_wallet"))
payee = d.pop("payee")
payee_type = d.pop("payee_type")
payee_wallet = UUID(d.pop("payee_wallet"))
created_at = isoparse(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
updated_at = isoparse(d.pop("updated_at"))
_uuid = d.pop("uuid", UNSET)
uuid: Union[Unset, UUID]
if isinstance(_uuid, Unset):
uuid = UNSET
else:
uuid = UUID(_uuid)
details = d.pop("details", UNSET)
application_withdraw = cls(
payer=payer,
payer_type=payer_type,
payer_wallet=payer_wallet,
payee=payee,
payee_type=payee_type,
payee_wallet=payee_wallet,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
uuid=uuid,
details=details,
)
application_withdraw.additional_properties = d
return application_withdraw
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,3 +1,4 @@
from collections.abc import Mapping
from typing import TYPE_CHECKING, Any, TypeVar, Union, cast
from attrs import define as _attrs_define
@ -6,24 +7,24 @@ from attrs import field as _attrs_field
from ..types import UNSET, Unset
if TYPE_CHECKING:
from ..models.user_transaction import UserTransaction
from ..models.account import Account
T = TypeVar("T", bound="PaginatedUserTransactionList")
T = TypeVar("T", bound="PaginatedAccountList")
@_attrs_define
class PaginatedUserTransactionList:
class PaginatedAccountList:
"""
Attributes:
count (int): Example: 123.
results (list['UserTransaction']):
next_ (Union[None, Unset, str]): Example: http://api.example.org/accounts/?page=4.
previous (Union[None, Unset, str]): Example: http://api.example.org/accounts/?page=2.
results (list['Account']):
next_ (Union[None, Unset, str]): Example: http://api.example.org/accounts/?offset=400&limit=100.
previous (Union[None, Unset, str]): Example: http://api.example.org/accounts/?offset=200&limit=100.
"""
count: int
results: list["UserTransaction"]
results: list["Account"]
next_: Union[None, Unset, str] = UNSET
previous: Union[None, Unset, str] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
@ -64,16 +65,16 @@ class PaginatedUserTransactionList:
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
from ..models.user_transaction import UserTransaction
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
from ..models.account import Account
d = src_dict.copy()
d = dict(src_dict)
count = d.pop("count")
results = []
_results = d.pop("results")
for results_item_data in _results:
results_item = UserTransaction.from_dict(results_item_data)
results_item = Account.from_dict(results_item_data)
results.append(results_item)
@ -95,15 +96,15 @@ class PaginatedUserTransactionList:
previous = _parse_previous(d.pop("previous", UNSET))
paginated_user_transaction_list = cls(
paginated_account_list = cls(
count=count,
results=results,
next_=next_,
previous=previous,
)
paginated_user_transaction_list.additional_properties = d
return paginated_user_transaction_list
paginated_account_list.additional_properties = d
return paginated_account_list
@property
def additional_keys(self) -> list[str]:

View file

@ -1,3 +1,4 @@
from collections.abc import Mapping
from typing import TYPE_CHECKING, Any, TypeVar, Union, cast
from attrs import define as _attrs_define
@ -6,24 +7,24 @@ from attrs import field as _attrs_field
from ..types import UNSET, Unset
if TYPE_CHECKING:
from ..models.application_transaction import ApplicationTransaction
from ..models.transaction import Transaction
T = TypeVar("T", bound="PaginatedApplicationTransactionList")
T = TypeVar("T", bound="PaginatedTransactionList")
@_attrs_define
class PaginatedApplicationTransactionList:
class PaginatedTransactionList:
"""
Attributes:
count (int): Example: 123.
results (list['ApplicationTransaction']):
next_ (Union[None, Unset, str]): Example: http://api.example.org/accounts/?page=4.
previous (Union[None, Unset, str]): Example: http://api.example.org/accounts/?page=2.
results (list['Transaction']):
next_ (Union[None, Unset, str]): Example: http://api.example.org/accounts/?offset=400&limit=100.
previous (Union[None, Unset, str]): Example: http://api.example.org/accounts/?offset=200&limit=100.
"""
count: int
results: list["ApplicationTransaction"]
results: list["Transaction"]
next_: Union[None, Unset, str] = UNSET
previous: Union[None, Unset, str] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
@ -64,16 +65,16 @@ class PaginatedApplicationTransactionList:
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
from ..models.application_transaction import ApplicationTransaction
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
from ..models.transaction import Transaction
d = src_dict.copy()
d = dict(src_dict)
count = d.pop("count")
results = []
_results = d.pop("results")
for results_item_data in _results:
results_item = ApplicationTransaction.from_dict(results_item_data)
results_item = Transaction.from_dict(results_item_data)
results.append(results_item)
@ -95,15 +96,15 @@ class PaginatedApplicationTransactionList:
previous = _parse_previous(d.pop("previous", UNSET))
paginated_application_transaction_list = cls(
paginated_transaction_list = cls(
count=count,
results=results,
next_=next_,
previous=previous,
)
paginated_application_transaction_list.additional_properties = d
return paginated_application_transaction_list
paginated_transaction_list.additional_properties = d
return paginated_transaction_list
@property
def additional_keys(self) -> list[str]:

View file

@ -0,0 +1,176 @@
import datetime
from collections.abc import Mapping
from typing import Any, TypeVar, Union
from uuid import UUID
from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse
from ..models.state_enum import StateEnum
from ..types import UNSET, Unset
T = TypeVar("T", bound="Transaction")
@_attrs_define
class Transaction:
"""
Attributes:
uuid (UUID):
payer (str):
payer_type (str):
payer_wallet (str):
payee (UUID):
payee_type (int):
payee_wallet (str):
created_at (datetime.datetime):
state (StateEnum): * `1` - created
* `2` - delayed
* `3` - pending
* `4` - incomplete
* `5` - success
* `6` - failed
* `7` - expected_failure
amount (int):
updated_at (datetime.datetime):
details (Any):
role (int):
delay (Union[Unset, int]):
"""
uuid: UUID
payer: str
payer_type: str
payer_wallet: str
payee: UUID
payee_type: int
payee_wallet: str
created_at: datetime.datetime
state: StateEnum
amount: int
updated_at: datetime.datetime
details: Any
role: int
delay: Union[Unset, int] = UNSET
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
def to_dict(self) -> dict[str, Any]:
uuid = str(self.uuid)
payer = self.payer
payer_type = self.payer_type
payer_wallet = self.payer_wallet
payee = str(self.payee)
payee_type = self.payee_type
payee_wallet = self.payee_wallet
created_at = self.created_at.isoformat()
state = self.state.value
amount = self.amount
updated_at = self.updated_at.isoformat()
details = self.details
role = self.role
delay = self.delay
field_dict: dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update(
{
"uuid": uuid,
"payer": payer,
"payer_type": payer_type,
"payer_wallet": payer_wallet,
"payee": payee,
"payee_type": payee_type,
"payee_wallet": payee_wallet,
"created_at": created_at,
"state": state,
"amount": amount,
"updated_at": updated_at,
"details": details,
"role": role,
}
)
if delay is not UNSET:
field_dict["delay"] = delay
return field_dict
@classmethod
def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
d = dict(src_dict)
uuid = UUID(d.pop("uuid"))
payer = d.pop("payer")
payer_type = d.pop("payer_type")
payer_wallet = d.pop("payer_wallet")
payee = UUID(d.pop("payee"))
payee_type = d.pop("payee_type")
payee_wallet = d.pop("payee_wallet")
created_at = isoparse(d.pop("created_at"))
state = StateEnum(d.pop("state"))
amount = d.pop("amount")
updated_at = isoparse(d.pop("updated_at"))
details = d.pop("details")
role = d.pop("role")
delay = d.pop("delay", UNSET)
transaction = cls(
uuid=uuid,
payer=payer,
payer_type=payer_type,
payer_wallet=payer_wallet,
payee=payee,
payee_type=payee_type,
payee_wallet=payee_wallet,
created_at=created_at,
state=state,
amount=amount,
updated_at=updated_at,
details=details,
role=role,
delay=delay,
)
transaction.additional_properties = d
return transaction
@property
def additional_keys(self) -> list[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View file

@ -1,8 +1,8 @@
"""Contains some shared types for properties"""
from collections.abc import MutableMapping
from collections.abc import Mapping, MutableMapping
from http import HTTPStatus
from typing import BinaryIO, Generic, Literal, Optional, TypeVar
from typing import IO, BinaryIO, Generic, Literal, Optional, TypeVar, Union
from attrs import define
@ -14,7 +14,15 @@ class Unset:
UNSET: Unset = Unset()
FileJsonType = tuple[Optional[str], BinaryIO, Optional[str]]
# The types that `httpx.Client(files=)` can accept, copied from that library.
FileContent = Union[IO[bytes], bytes, str]
FileTypes = Union[
# (filename, file (or bytes), content_type)
tuple[Optional[str], FileContent, Optional[str]],
# (filename, file (or bytes), content_type, headers)
tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]],
]
RequestFiles = list[tuple[str, FileTypes]]
@define
@ -25,7 +33,7 @@ class File:
file_name: Optional[str] = None
mime_type: Optional[str] = None
def to_tuple(self) -> FileJsonType:
def to_tuple(self) -> FileTypes:
"""Return a tuple representation that httpx will accept for multipart/form-data"""
return self.file_name, self.payload, self.mime_type
@ -43,4 +51,4 @@ class Response(Generic[T]):
parsed: Optional[T]
__all__ = ["UNSET", "File", "FileJsonType", "Response", "Unset"]
__all__ = ["UNSET", "File", "FileTypes", "RequestFiles", "Response", "Unset"]

View file

@ -6,13 +6,13 @@ from django.core.cache import cache
from django.db import models
from httpx import Request
from gooyal_wallet_client import AuthenticatedClient
from gooyal_wallet_client.models import MyWallet, UserTransaction, ApplicationDeposit, ApplicationWithdraw
from gooyal_wallet_client.api.wallet import (wallet_api_application_deposit_create,
from utils.clients.gooyal_wallet_client import AuthenticatedClient
from utils.clients.gooyal_wallet_client.models import Transaction, Account, ApplicationDeposit, ApplicationWithdraw
from utils.clients.gooyal_wallet_client.api.wallet import (wallet_api_application_deposit_create,
wallet_api_application_deposit_verify_retrieve,
wallet_api_application_withdraw_create,
wallet_api_application_withdraw_verify_retrieve)
from gooyal_wallet_client.types import Response
from utils.clients.gooyal_wallet_client.types import Response
from django.conf import Settings
@ -37,11 +37,11 @@ def login_as_client_credentials():
data = {
"grant_type": 'client_credentials',
"scope": settings.SCOPES,
"scope": settings.OAUTH2_PROVIDER_SCOPES,
}
auth = (settings.CLIENT_ID, settings.CLIENT_SECRET)
auth = (settings.OAUTH2_PROVIDER_CLIENT_ID, settings.OAUTH2_PROVIDER_CLIENT_SECRET)
response = requests.post(f'{settings.BASE_OAUTH2_PROVIDER_PUBLIC_URL}/token/',
response = requests.post(f'{settings.OAUTH2_PROVIDER_BASE_PUBLIC_URL}/token/',
data=data,
auth=auth)
print(response.content)
@ -73,52 +73,41 @@ def get_client():
return client
def deposit_to_user_wallet_submit(data):
def deposit_to_user_wallet_submit(payer_wallet, data):
class Tmp():
def to_dict(self):
return data
deposit_data = Tmp()
client = get_client()
response: ApplicationDeposit = wallet_api_application_deposit_create.sync(client=client, body=deposit_data)
response: ApplicationDeposit = wallet_api_application_deposit_create.sync(payer_wallet=payer_wallet,
client=client,
body=deposit_data)
print(response)
return response
def deposit_to_user_wallet_verify(uuid):
def deposit_to_user_wallet_verify(payer_wallet, uuid):
client = get_client()
response: ApplicationDeposit = wallet_api_application_deposit_verify_retrieve.sync(uuid=uuid, client=client)
response: ApplicationDeposit = wallet_api_application_deposit_verify_retrieve.sync(payer_wallet=payer_wallet, uuid=uuid, client=client)
print(response)
return response
def withdraw_from_user_wallet_submit(data):
def withdraw_from_user_wallet_submit(payee_wallet, data):
class Tmp():
def to_dict(self):
return data
withdraw_data = Tmp()
client = get_client()
response: ApplicationWithdraw = wallet_api_application_withdraw_create.sync(client=client, body=withdraw_data)
response: ApplicationWithdraw = wallet_api_application_withdraw_create.sync(payee_wallet=payee_wallet, client=client, body=withdraw_data)
print(response)
return response
def withdraw_from_user_wallet_verify(uuid):
def withdraw_from_user_wallet_verify(payee_wallet, uuid):
client = get_client()
response: ApplicationWithdraw = wallet_api_application_withdraw_verify_retrieve.sync(uuid=uuid, client=client)
response: ApplicationWithdraw = wallet_api_application_withdraw_verify_retrieve.sync(payee_wallet=payee_wallet, uuid=uuid, client=client)
print(response)
return response
sample_data = {
"uuid": "3fa85f64-5717-4562-b3fc-2c963f66afb1",
"payee_id": "5d66d02e-6087-4b0a-bb0c-291d5c11755a",
"payee_type": 1,
"amount": 2000,
"details": "string",
}

9
utils/commons.py Normal file
View file

@ -0,0 +1,9 @@
from main import settings
def calculate_pna_commission(amount: int) -> int:
commission = settings.COMMISSION_LEVEL1
if settings.COMMISSION_LEVEL2_MIN_AMOUNT <= amount <= settings.COMMISSION_LEVEL2_MAX_AMOUNT:
commission = settings.COMMISSION_LEVEL2_RATE * amount
elif settings.COMMISSION_LEVEL2_MAX_AMOUNT < amount:
commission = settings.COMMISSION_LEVEL3
return commission

51
utils/exceptions.py Normal file
View file

@ -0,0 +1,51 @@
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):
logger.exception(exc)
# پاسخ پیش‌فرض 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
)

14
utils/i18n.py Normal file
View file

@ -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)

4
utils/logs/__init__.py Normal file
View file

@ -0,0 +1,4 @@
from .formatters import LokiFormatter
from .handlers import LokiHandler
__all__ = ['LokiHandler', 'LokiFormatter']

77
utils/logs/formatters.py Normal file
View file

@ -0,0 +1,77 @@
import logging
import socket
from datetime import datetime
from logging import BASIC_FORMAT
class LokiFormatter(logging.Formatter):
asctime_search = "%(asctime)"
tz = "UTC"
source = "Loki"
src_host = "localhost"
tags = {}
def __init__(self, fmt, dfmt, style, fqdn=False):
super(LokiFormatter, self).__init__()
self.fmt = fmt or BASIC_FORMAT
self.dfmt = dfmt or "%Y-%m-%d %H:%M:%S"
self.style = style
if fqdn:
self.host = socket.getfqdn()
else:
self.host = socket.gethostname()
def format_timestamp(self, time):
return str(int(time * 10**9))
def usesTime(self):
return self.fmt.find(self.asctime_search) >= 0
def formatMessage(self, record):
try:
return self.fmt % record.__dict__
except KeyError as e:
raise ValueError("Formatting field not found in record: %s" % e)
def format(self, record):
record.message = record.getMessage()
if self.usesTime():
record.asctime = self.formatTime(record, self.dfmt)
message = self.formatMessage(record)
if record.exc_info:
if not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
if record.exc_text:
if message[-1:] != "\n":
message = message + "\n"
message = message + record.exc_text
if record.stack_info:
if message[-1:] != "\n":
message = message + "\n"
message = message + self.formatStack(record.stack_info)
message = {
"streams": [
{
"stream": {
**self.tags,
},
"values": [
[
self.format_timestamp(record.created),
message,
]
],
}
]
}
return message

57
utils/logs/handlers.py Normal file
View file

@ -0,0 +1,57 @@
import logging
import sys
from threading import Thread
import requests
class LokiHandler(logging.Handler):
def __init__(
self,
timeout=0.5,
url="http://localhost:3100/loki/api/v1/push",
auth=None,
tags={},
mode="sync",
):
super(LokiHandler, self).__init__()
self._url = url
self._timeout = timeout
self._auth = auth
self._tags = tags
self._mode = mode
def emit(self, record):
try:
payload = self.formatter.format(record)
self._push_message(
self._url, json=payload, timeout=self._timeout, auth=self._auth
)
except requests.exceptions.ReadTimeout:
sys.stderr.write("Loki connection timed out\n")
except Exception as e:
sys.stderr.write(f"Loki connection failed with: {e}\n")
def setFormatter(self, fmt):
fmt.tags = self._tags
self.formatter = fmt
def _push_message(self, *args, **kwargs):
if self._mode == "sync":
return _push_message(*args, **kwargs)
if self._mode == "thread":
return Thread(target=_push_message, args=args, kwargs=kwargs).start()
def _push_message(*args, **kwargs):
response = requests.post(*args, **kwargs)
if response.status_code != 204:
sys.stderr.write(
f"Got status {response.status_code} from loki with message: {response.text}\n"
)