Adds manual payment request functionality
Enables users to request manual payments from the Castle and provides admin functions to approve or reject these requests. Introduces the `manual_payment_requests` table and related CRUD operations. Adds API endpoints for creating, retrieving, approving, and rejecting manual payment requests. Updates the UI to allow users to request payments and for admins to review pending requests.
This commit is contained in:
parent
3a26d963dc
commit
c2d9b39f29
5 changed files with 520 additions and 11 deletions
140
crud.py
140
crud.py
|
|
@ -557,3 +557,143 @@ async def get_all_user_wallet_settings() -> list[StoredUserWalletSettings]:
|
|||
{},
|
||||
StoredUserWalletSettings,
|
||||
)
|
||||
|
||||
|
||||
# ===== MANUAL PAYMENT REQUESTS =====
|
||||
|
||||
|
||||
async def create_manual_payment_request(
|
||||
user_id: str, amount: int, description: str
|
||||
) -> "ManualPaymentRequest":
|
||||
"""Create a new manual payment request"""
|
||||
from .models import ManualPaymentRequest
|
||||
|
||||
request_id = urlsafe_short_hash()
|
||||
request = ManualPaymentRequest(
|
||||
id=request_id,
|
||||
user_id=user_id,
|
||||
amount=amount,
|
||||
description=description,
|
||||
status="pending",
|
||||
created_at=datetime.now(),
|
||||
)
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
INSERT INTO manual_payment_requests (id, user_id, amount, description, status, created_at)
|
||||
VALUES (:id, :user_id, :amount, :description, :status, :created_at)
|
||||
""",
|
||||
{
|
||||
"id": request.id,
|
||||
"user_id": request.user_id,
|
||||
"amount": request.amount,
|
||||
"description": request.description,
|
||||
"status": request.status,
|
||||
"created_at": request.created_at,
|
||||
},
|
||||
)
|
||||
|
||||
return request
|
||||
|
||||
|
||||
async def get_manual_payment_request(request_id: str) -> Optional["ManualPaymentRequest"]:
|
||||
"""Get a manual payment request by ID"""
|
||||
from .models import ManualPaymentRequest
|
||||
|
||||
return await db.fetchone(
|
||||
"SELECT * FROM manual_payment_requests WHERE id = :id",
|
||||
{"id": request_id},
|
||||
ManualPaymentRequest,
|
||||
)
|
||||
|
||||
|
||||
async def get_user_manual_payment_requests(
|
||||
user_id: str, limit: int = 100
|
||||
) -> list["ManualPaymentRequest"]:
|
||||
"""Get all manual payment requests for a specific user"""
|
||||
from .models import ManualPaymentRequest
|
||||
|
||||
return await db.fetchall(
|
||||
"""
|
||||
SELECT * FROM manual_payment_requests
|
||||
WHERE user_id = :user_id
|
||||
ORDER BY created_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{"user_id": user_id, "limit": limit},
|
||||
ManualPaymentRequest,
|
||||
)
|
||||
|
||||
|
||||
async def get_all_manual_payment_requests(
|
||||
status: Optional[str] = None, limit: int = 100
|
||||
) -> list["ManualPaymentRequest"]:
|
||||
"""Get all manual payment requests, optionally filtered by status"""
|
||||
from .models import ManualPaymentRequest
|
||||
|
||||
if status:
|
||||
return await db.fetchall(
|
||||
"""
|
||||
SELECT * FROM manual_payment_requests
|
||||
WHERE status = :status
|
||||
ORDER BY created_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{"status": status, "limit": limit},
|
||||
ManualPaymentRequest,
|
||||
)
|
||||
else:
|
||||
return await db.fetchall(
|
||||
"""
|
||||
SELECT * FROM manual_payment_requests
|
||||
ORDER BY created_at DESC
|
||||
LIMIT :limit
|
||||
""",
|
||||
{"limit": limit},
|
||||
ManualPaymentRequest,
|
||||
)
|
||||
|
||||
|
||||
async def approve_manual_payment_request(
|
||||
request_id: str, reviewed_by: str, journal_entry_id: str
|
||||
) -> Optional["ManualPaymentRequest"]:
|
||||
"""Approve a manual payment request"""
|
||||
from .models import ManualPaymentRequest
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE manual_payment_requests
|
||||
SET status = 'approved', reviewed_at = :reviewed_at, reviewed_by = :reviewed_by, journal_entry_id = :journal_entry_id
|
||||
WHERE id = :id
|
||||
""",
|
||||
{
|
||||
"id": request_id,
|
||||
"reviewed_at": datetime.now(),
|
||||
"reviewed_by": reviewed_by,
|
||||
"journal_entry_id": journal_entry_id,
|
||||
},
|
||||
)
|
||||
|
||||
return await get_manual_payment_request(request_id)
|
||||
|
||||
|
||||
async def reject_manual_payment_request(
|
||||
request_id: str, reviewed_by: str
|
||||
) -> Optional["ManualPaymentRequest"]:
|
||||
"""Reject a manual payment request"""
|
||||
from .models import ManualPaymentRequest
|
||||
|
||||
await db.execute(
|
||||
"""
|
||||
UPDATE manual_payment_requests
|
||||
SET status = 'rejected', reviewed_at = :reviewed_at, reviewed_by = :reviewed_by
|
||||
WHERE id = :id
|
||||
""",
|
||||
{
|
||||
"id": request_id,
|
||||
"reviewed_at": datetime.now(),
|
||||
"reviewed_by": reviewed_by,
|
||||
},
|
||||
)
|
||||
|
||||
return await get_manual_payment_request(request_id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue