STABLE: Final schema sync, optimized gitignore
This commit is contained in:
@@ -1,125 +1,36 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
# backend/app/api/v1/endpoints/billing.py
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy import select, text
|
||||
from app.api.deps import get_db, get_current_user
|
||||
from typing import List, Dict
|
||||
from app.models.identity import User, Wallet
|
||||
from app.models.audit import FinancialLedger # JAVÍTVA: Tranzakciós napló
|
||||
import secrets
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# 1. EGYENLEG LEKÉRDEZÉSE (A felhasználó Széfjéhez kötve)
|
||||
@router.get("/balance")
|
||||
async def get_balance(db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
|
||||
"""
|
||||
Visszaadja a felhasználó aktuális kreditegyenlegét és a Széfje (Cége) nevét.
|
||||
"""
|
||||
query = text("""
|
||||
SELECT
|
||||
uc.balance,
|
||||
c.name as company_name
|
||||
FROM data.user_credits uc
|
||||
JOIN data.companies c ON uc.user_id = c.owner_id
|
||||
WHERE uc.user_id = :user_id
|
||||
LIMIT 1
|
||||
""")
|
||||
result = await db.execute(query, {"user_id": current_user.id})
|
||||
row = result.fetchone()
|
||||
|
||||
if not row:
|
||||
return {
|
||||
"company_name": "Privát Széf",
|
||||
"balance": 0.0,
|
||||
"currency": "Credit"
|
||||
}
|
||||
|
||||
async def get_balance(db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)):
|
||||
stmt = select(Wallet).where(Wallet.user_id == current_user.id)
|
||||
wallet = (await db.execute(stmt)).scalar_one_or_none()
|
||||
return {
|
||||
"company_name": row.company_name,
|
||||
"balance": float(row.balance),
|
||||
"currency": "Credit"
|
||||
"earned": float(wallet.earned_credits) if wallet else 0,
|
||||
"purchased": float(wallet.purchased_credits) if wallet else 0,
|
||||
"service_coins": float(wallet.service_coins) if wallet else 0
|
||||
}
|
||||
|
||||
# 2. TRANZAKCIÓS ELŐZMÉNYEK
|
||||
@router.get("/history")
|
||||
async def get_history(db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
|
||||
"""
|
||||
Kilistázza a kreditmozgásokat (bevételek, költések, voucherek).
|
||||
"""
|
||||
query = text("""
|
||||
SELECT amount, reason, created_at
|
||||
FROM data.credit_transactions
|
||||
WHERE user_id = :user_id
|
||||
ORDER BY created_at DESC
|
||||
""")
|
||||
result = await db.execute(query, {"user_id": current_user.id})
|
||||
return [dict(row._mapping) for row in result.fetchall()]
|
||||
|
||||
# 3. VOUCHER BEVÁLTÁS (A rendszer gazdaságának motorja)
|
||||
@router.post("/vouchers/redeem")
|
||||
async def redeem_voucher(code: str, db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
|
||||
"""
|
||||
Bevált egy kódot, és jóváírja az értékét a felhasználó egyenlegén.
|
||||
"""
|
||||
# 1. Voucher ellenőrzése
|
||||
check_query = text("""
|
||||
SELECT id, value, is_used, expires_at
|
||||
FROM data.vouchers
|
||||
WHERE code = :code AND is_used = False AND (expires_at > now() OR expires_at IS NULL)
|
||||
""")
|
||||
res = await db.execute(check_query, {"code": code.strip().upper()})
|
||||
voucher = res.fetchone()
|
||||
|
||||
async def redeem_voucher(code: str, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)):
|
||||
check = await db.execute(text("SELECT * FROM data.vouchers WHERE code = :c AND is_used = False"), {"c": code.upper()})
|
||||
voucher = check.fetchone()
|
||||
if not voucher:
|
||||
raise HTTPException(status_code=400, detail="Érvénytelen, lejárt vagy már felhasznált kód.")
|
||||
raise HTTPException(status_code=400, detail="Érvénytelen kód.")
|
||||
|
||||
# 2. Egyenleg frissítése (vagy létrehozása, ha még nincs sor a user_credits-ben)
|
||||
update_balance = text("""
|
||||
INSERT INTO data.user_credits (user_id, balance)
|
||||
VALUES (:u, :v)
|
||||
ON CONFLICT (user_id) DO UPDATE SET balance = data.user_credits.balance + :v
|
||||
""")
|
||||
await db.execute(update_balance, {"u": current_user.id, "v": voucher.value})
|
||||
|
||||
# 3. Tranzakció naplózása
|
||||
log_transaction = text("""
|
||||
INSERT INTO data.credit_transactions (user_id, amount, reason)
|
||||
VALUES (:u, :v, :r)
|
||||
""")
|
||||
await db.execute(log_transaction, {
|
||||
"u": current_user.id,
|
||||
"v": voucher.value,
|
||||
"r": f"Voucher beváltva: {code}"
|
||||
})
|
||||
|
||||
# 4. Voucher megjelölése felhasználtként
|
||||
await db.execute(text("""
|
||||
UPDATE data.vouchers
|
||||
SET is_used = True, used_by = :u, used_at = now()
|
||||
WHERE id = :vid
|
||||
"""), {"u": current_user.id, "vid": voucher.id})
|
||||
stmt = select(Wallet).where(Wallet.user_id == current_user.id)
|
||||
wallet = (await db.execute(stmt)).scalar_one_or_none()
|
||||
wallet.purchased_credits += voucher.value
|
||||
|
||||
db.add(FinancialLedger(user_id=current_user.id, amount=voucher.value, transaction_type="VOUCHER_REDEEM", details={"code": code}))
|
||||
await db.execute(text("UPDATE data.vouchers SET is_used=True, used_by=:u WHERE id=:v"), {"u": current_user.id, "v": voucher.id})
|
||||
await db.commit()
|
||||
return {"status": "success", "added_value": float(voucher.value), "message": "Kredit jóváírva!"}
|
||||
|
||||
# 4. ADMIN: VOUCHER GENERÁLÁS (Csak Neked)
|
||||
@router.post("/vouchers/generate", include_in_schema=True)
|
||||
async def generate_vouchers(
|
||||
count: int = 1,
|
||||
value: float = 500.0,
|
||||
batch_name: str = "ADMIN_GEN",
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
Tömeges voucher generálás az admin felületről.
|
||||
"""
|
||||
generated_codes = []
|
||||
for _ in range(count):
|
||||
# Generálunk egy SF-XXXX-XXXX formátumú kódot
|
||||
code = f"SF-{secrets.token_hex(3).upper()}-{secrets.token_hex(3).upper()}"
|
||||
await db.execute(text("""
|
||||
INSERT INTO data.vouchers (code, value, batch_id, expires_at)
|
||||
VALUES (:c, :v, :b, now() + interval '90 days')
|
||||
"""), {"c": code, "v": value, "b": batch_name})
|
||||
generated_codes.append(code)
|
||||
|
||||
await db.commit()
|
||||
return {"batch": batch_name, "count": count, "codes": generated_codes}
|
||||
return {"status": "success", "added": float(voucher.value)}
|
||||
Reference in New Issue
Block a user