Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/adapters/api/v1/admin/wallet_admin.py
2026-05-18 16:50:15 +00:00

234 lines
7.2 KiB
Python
Executable file

from __future__ import annotations
from typing import Dict, Any, List
from datetime import datetime, date
from decimal import Decimal
from fastapi import APIRouter, Depends, Request, Body, Path, Query
from sqlalchemy.orm import Session
from adapters.db.session import get_db
from app.core.auth_dependency import get_current_user, AuthContext
from app.core.responses import success_response, ApiError
from adapters.db.models.wallet import WalletAccount, WalletPayout
from app.services.wallet_service import (
refund_transaction,
settle_payout,
approve_payout_request,
list_wallet_payouts_admin,
get_wallet_payout_admin,
get_wallet_payouts_stats_admin,
)
router = APIRouter(prefix="/admin/wallets", tags=["admin-wallet"])
def _parse_iso_datetime(value) -> datetime | None:
if value is None:
return None
if isinstance(value, datetime):
return value
if isinstance(value, date):
return datetime.combine(value, datetime.min.time())
try:
return datetime.fromisoformat(str(value))
except Exception as exc:
raise ApiError("INVALID_DATE", f"تاریخ نامعتبر است: {value}") from exc
@router.get(
"",
summary="فهرست کیف‌پول کسب‌وکارها",
)
def list_wallets_admin(
request: Request,
limit: int = Query(50, ge=1, le=200),
skip: int = Query(0, ge=0),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
q = db.query(WalletAccount).order_by(WalletAccount.id.desc())
items = q.offset(skip).limit(limit).all()
data = [
{
"id": it.id,
"business_id": it.business_id,
"available_balance": float(it.available_balance or 0),
"pending_balance": float(it.pending_balance or 0),
"status": it.status,
}
for it in items
]
return success_response(data, request)
@router.post(
"/{business_id}/refunds",
summary="ایجاد استرداد (مدیریتی)",
)
def create_refund_admin(
request: Request,
business_id: int,
payload: Dict[str, Any] = Body(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
tx_id = int(payload.get("transaction_id") or 0)
amount = payload.get("amount")
reason = payload.get("reason")
from decimal import Decimal
data = refund_transaction(db, tx_id, amount=Decimal(str(amount)) if amount is not None else None, reason=reason)
return success_response(data, request, message="REFUND_CREATED")
@router.get(
"/payouts/stats",
summary="آمار کلی درخواست‌های تسویه کیف‌پول",
)
def get_wallet_payouts_stats_endpoint(
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
data = get_wallet_payouts_stats_admin(db)
return success_response(data, request)
@router.post(
"/payouts/table",
summary="لیست درخواست‌های تسویه کیف‌پول (برای جدول)",
)
def list_wallet_payouts_admin_table_endpoint(
request: Request,
payload: Dict[str, Any] = Body(default_factory=dict),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
# Extract pagination params
take = int(payload.get("take") or 20)
skip = int(payload.get("skip") or 0)
# Extract filters
statuses = None
business_id = None
filters = payload.get("filters") or []
for f in filters:
prop = str(f.get("property") or "").lower()
op = str(f.get("operator") or "")
val = f.get("value")
if prop == "status" and op == "in" and val is not None:
if isinstance(val, list):
statuses = [str(v).strip() for v in val if v]
elif isinstance(val, str):
statuses = [s.strip() for s in val.split(",") if s.strip()]
elif prop == "business_id" and val is not None:
business_id = int(val) if isinstance(val, (int, str)) and str(val).strip() else None
data = list_wallet_payouts_admin(
db,
statuses=statuses,
business_id=business_id,
limit=take,
skip=skip,
)
# Compute total
try:
q = db.query(WalletPayout)
if statuses:
q = q.filter(WalletPayout.status.in_(statuses))
if business_id:
q = q.filter(WalletPayout.business_id == int(business_id))
total = q.count()
except Exception:
total = len(data.get("items", []))
page = (skip // take) + 1 if take > 0 else 1
total_pages = (total + take - 1) // take if take > 0 else 1
resp = {
"items": data.get("items", []),
"total": total,
"page": page,
"limit": take,
"total_pages": total_pages,
}
return success_response(resp, request)
@router.get(
"/payouts/{payout_id}",
summary="جزئیات درخواست تسویه کیف‌پول",
)
def get_wallet_payout_admin_endpoint(
request: Request,
payout_id: int = Path(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
data = get_wallet_payout_admin(db, payout_id)
return success_response(data, request)
@router.put(
"/payouts/{payout_id}/approve",
summary="تایید درخواست تسویه (مدیریتی)",
)
def approve_payout_admin(
request: Request,
payout_id: int = Path(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
data = approve_payout_request(db, payout_id, ctx.get_user_id())
return success_response(data, request, message="PAYOUT_APPROVED")
@router.put(
"/payouts/{payout_id}/settle",
summary="تسویه درخواست Payout (مدیریتی)",
)
def settle_payout_admin(
request: Request,
payout_id: int,
payload: Dict[str, Any] = Body(...),
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user),
) -> dict:
if not ctx.has_any_permission("system_settings", "superadmin"):
raise ApiError("FORBIDDEN", "Missing permission: system_settings", http_status=403)
track_code = str(payload.get("bank_tracking_code") or "").strip()
if not track_code:
raise ApiError("TRACKING_REQUIRED", "کد پیگیری بانک الزامی است", http_status=400)
fee_amount = payload.get("fee_amount")
note = payload.get("note")
settlement_date_value = payload.get("settlement_date")
if not settlement_date_value:
raise ApiError("SETTLEMENT_DATE_REQUIRED", "تاریخ واریز الزامی است", http_status=400)
settlement_dt = _parse_iso_datetime(settlement_date_value)
data = settle_payout(
db,
payout_id,
ctx.get_user_id(),
settlement_date=settlement_dt,
bank_tracking_code=track_code,
fee_amount=Decimal(str(fee_amount)) if fee_amount is not None else None,
note=note,
auto_approve_if_requested=True,
)
return success_response(data, request, message="PAYOUT_SETTLED")