felhasználói felületre pü

This commit is contained in:
Roo
2026-07-27 08:39:18 +00:00
parent c9118bf52f
commit 6f28d3e70d
72 changed files with 6311 additions and 749 deletions

View File

@@ -573,16 +573,22 @@ class AtomicTransactionManager:
# Convert to dictionary format
transactions = []
for entry in ledger_entries:
# Extract description from JSONB details field (legacy compatibility)
desc = None
if entry.details and isinstance(entry.details, dict):
desc = entry.details.get("description") or entry.details.get("desc") or None
elif entry.details and isinstance(entry.details, str):
desc = entry.details
transactions.append({
"id": entry.id,
"user_id": entry.user_id,
"amount": float(entry.amount),
"entry_type": entry.entry_type.value,
"wallet_type": entry.wallet_type.value if entry.wallet_type else None,
"description": entry.description,
"description": desc,
"transaction_id": str(entry.transaction_id),
"reference_type": entry.reference_type,
"reference_id": entry.reference_id,
"reference_type": None,
"reference_id": None,
"balance_after": float(entry.balance_after) if entry.balance_after else None,
"created_at": entry.created_at.isoformat() if entry.created_at else None
})
@@ -622,15 +628,15 @@ class AtomicTransactionManager:
return {
"wallet_id": wallet.id,
"balances": {
"earned": float(wallet.earned_credits),
"purchased": float(wallet.purchased_credits),
"service_coins": float(wallet.service_coins),
"voucher": float(voucher_balance),
"earned": float(wallet.earned_credits or 0),
"purchased": float(wallet.purchased_credits or 0),
"service_coins": float(wallet.service_coins or 0),
"voucher": float(voucher_balance or 0),
"total": float(
wallet.earned_credits +
wallet.purchased_credits +
wallet.service_coins +
voucher_balance
(wallet.earned_credits or 0) +
(wallet.purchased_credits or 0) +
(wallet.service_coins or 0) +
(voucher_balance or 0)
)
},
"recent_transactions": recent_transactions,

View File

@@ -33,6 +33,7 @@ from app.models.marketplace.commission import (
CommissionTier,
)
from app.models.identity.identity import User, Wallet
from app.models.system import SystemParameter
from app.models.system.audit import (
FinancialLedger,
LedgerEntryType,
@@ -589,26 +590,59 @@ async def _credit_commission_to_wallet(
)
async def _get_inactivity_threshold(db: AsyncSession, default: int = 180) -> int:
"""
Read the inactivity_threshold_days from system.system_parameters.
Falls back to `default` (180) if not found.
"""
try:
stmt = select(SystemParameter).where(
SystemParameter.key == "inactivity_threshold_days",
SystemParameter.scope_level == "global",
SystemParameter.is_active == True,
)
result = await db.execute(stmt)
param = result.scalar_one_or_none()
if param is not None:
val = param.value
if isinstance(val, dict):
return int(val.get("value", val.get("days", default)))
return int(val)
except Exception as e:
logger.warning(
f"Failed to read inactivity_threshold_days from DB: {e}. "
f"Falling back to {default}."
)
return default
async def _is_user_recently_active(
db: AsyncSession,
user_id: int,
inactivity_days: int = 180,
inactivity_days: Optional[int] = None,
) -> bool:
"""
Check if a user has been active within the last `inactivity_days` days.
Check if a user has been active within the inactivity threshold.
A user is considered active if:
1. Their subscription is active (subscription_expires_at > now), OR
2. They have a FinancialLedger entry within the inactivity window.
The inactivity threshold is read from system.system_parameters
(key: inactivity_threshold_days), falling back to 180 days.
Args:
db: Database session.
user_id: The user to check.
inactivity_days: Number of days of inactivity before considered inactive.
inactivity_days: Optional override. If None, reads from DB settings.
Returns:
True if the user is recently active, False otherwise.
"""
# Resolve threshold: parameter override or DB setting
if inactivity_days is None:
inactivity_days = await _get_inactivity_threshold(db)
# Check subscription status first
user = await _lookup_user(db, user_id)
if not user:

View File

@@ -393,22 +393,42 @@ class FinancialOrchestrator:
await db.flush()
# 3. Pénztárca egyenleg visszaállítása
# JAVÍTÁS: A Wallet modellben NINCS "wallet_type" és "balance" mező.
# A usernek egyetlen wallet-je van (user_id UNIQUE constraint),
# a credit típusok külön oszlopokban: earned_credits, purchased_credits, service_coins.
# A wallet_type-t az eredeti FinancialLedger bejegyzésből olvassuk ki,
# és a megfelelő oszlopot frissítjük (pont mint process_payment()-ben).
wallet_query = select(Wallet).where(
and_(
Wallet.user_id == original_entry.user_id,
Wallet.wallet_type == original_entry.wallet_type
)
Wallet.user_id == original_entry.user_id
).with_for_update()
wallet_result = await db.execute(wallet_query)
wallet = wallet_result.scalar_one_or_none()
if wallet:
new_balance = wallet.balance - original_entry.amount
wallet_type = original_entry.wallet_type
update_values = {}
if wallet_type == WalletType.EARNED:
new_balance = Decimal(str(wallet.earned_credits)) + original_entry.amount
update_values['earned_credits'] = float(new_balance)
elif wallet_type == WalletType.PURCHASED:
new_balance = Decimal(str(wallet.purchased_credits)) + original_entry.amount
update_values['purchased_credits'] = float(new_balance)
elif wallet_type == WalletType.SERVICE_COINS:
new_balance = Decimal(str(wallet.service_coins)) + original_entry.amount
update_values['service_coins'] = float(new_balance)
elif wallet_type == WalletType.VOUCHER:
# VOUCHER típusnál nincs dedikált mező, SERVICE_COINS-ba tesszük
new_balance = Decimal(str(wallet.service_coins)) + original_entry.amount
update_values['service_coins'] = float(new_balance)
else:
raise ValueError(f"Ismeretlen wallet_type: {wallet_type}")
await db.execute(
update(Wallet)
.where(Wallet.id == wallet.id)
.values(balance=new_balance)
.values(**update_values)
)
# 4. Számlakiállító bevételének csökkentése