felhasználói felületre pü
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user