From 8a5ce82afa5b45bfc824c04b838ea646b705ef33 Mon Sep 17 00:00:00 2001 From: adevopg Date: Tue, 14 Jul 2026 20:25:54 +0000 Subject: [PATCH] Rango de cuenta por TOTAL DONADO (Stripe + SumUp), no por saldo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El nivel/rango usaba el saldo de PD actual, que baja al gastar. Ahora se basa en el total donado = suma de pagos confirmados (Stripe mode test/live + SumUp), convertidos a PD (amount * 100). Cuenta todas las pasarelas y donaciones mixtas y no baja al gastar PD. Se usa max(donatedPD, saldo) para no rebajar el rango a nadie (p.ej. PD de promo). getAccountDashboard expone donatedPD. Verificado: cuenta 15 con €43 en pagos -> Nivel 11 aunque el saldo sea 0. Co-Authored-By: Claude Opus 4.8 (1M context) --- web-next/app/[locale]/my-account/page.tsx | 4 +++- web-next/lib/account.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/web-next/app/[locale]/my-account/page.tsx b/web-next/app/[locale]/my-account/page.tsx index cfe94a2..c93969d 100644 --- a/web-next/app/[locale]/my-account/page.tsx +++ b/web-next/app/[locale]/my-account/page.tsx @@ -45,7 +45,9 @@ export default async function AccountPage({ params }: { params: Promise<{ locale const data = await getAccountDashboard(session, locale) const admin = await isAdmin(session) - const rank = getAccountRank(data.dp) + // El rango se basa en el TOTAL DONADO (Stripe + SumUp, sin bajar al gastar); + // se usa el máximo con el saldo actual para no rebajar el rango a nadie. + const rank = getAccountRank(Math.max(data.donatedPD, data.dp)) // Cuentas de juego de la Battle.net (para el selector si hay más de una). const games = await getGameAccounts(session.bnetId ?? 0) diff --git a/web-next/lib/account.ts b/web-next/lib/account.ts index c921c8b..24e5960 100644 --- a/web-next/lib/account.ts +++ b/web-next/lib/account.ts @@ -2,6 +2,7 @@ import type { RowDataPacket } from 'mysql2' import { db, DB } from './db' import type { SessionData } from './session' import { getZoneName, getClassCss, getCharacterImage, getRaceName, getClassName } from './character-info' +import { PD_PER_UNIT } from './dpoints' // Rango de la cuenta según los PD (14 niveles). Umbral = PD mínimos por nivel. const RANK_FILES = [ @@ -43,6 +44,7 @@ export interface AccountDashboard { lastAttemptIp: string dp: number vp: number + donatedPD: number battlepayCredits: number securityTokenDate: string | null isBanned: boolean @@ -71,6 +73,21 @@ export async function getAccountDashboard(session: SessionData, locale = 'es'): /* ignore */ } + // Total donado (en PD) para el rango: suma de TODOS los pagos confirmados + // (Stripe mode test/live + SumUp mode sumup), convertidos a PD. Cuenta todas + // las pasarelas y donaciones mixtas, y NO baja al gastar PD (a diferencia del + // saldo). El rango usará el máximo entre esto y el saldo actual. + let donatedPD = 0 + try { + const [d] = await db(DB.default).query( + "SELECT COALESCE(SUM(amount), 0) AS total FROM home_stripelog WHERE account_id = ? AND fulfilled = 1 AND mode IN ('sumup', 'test', 'live')", + [accountId], + ) + donatedPD = Math.round(Number(d[0]?.total ?? 0) * PD_PER_UNIT) + } catch { + /* ignore */ + } + let battlepayCredits = 0 try { const [c] = await db(DB.auth).query( @@ -179,6 +196,7 @@ export async function getAccountDashboard(session: SessionData, locale = 'es'): lastAttemptIp, dp, vp, + donatedPD, battlepayCredits, securityTokenDate, isBanned,