Monitorear uso
Exportar contenido
Visualiza tu consumo actual frente a los límites de tu plan.
- Ve a la pestaña “Uso”
- Se muestran 4 métricas principales con barras de progreso:
- Usuarios: Usuarios activos vs. límite del plan
- Facturas: Facturas emitidas este mes vs. límite mensual
- Clientes: Clientes totales vs. límite del plan
- Almacenamiento: Espacio usado vs. límite del plan
- Cada barra indica el porcentaje de uso:
- 🟢 Verde: menos de 75% del límite
- 🟡 Amarillo: 75-90% del límite
- 🔴 Rojo: más de 90% del límite
- Al alcanzar el 100%, aparece alerta sugiriendo upgrade
Errores comunes
Sección titulada «Errores comunes»“No se pudo cargar el uso”
Causa: Error temporal al calcular estadísticas.
Solución:
- Recarga la página
- Si persiste, verifica que tengas suscripción activa
- Contacta a soporte si continúa el error
Detalles técnicos
Sección titulada «Detalles técnicos»Cálculo de límites y uso
Componente: UsageLimitsCard
Ubicación: src/panels/owner/subscriptions/components/management/UsageLimitsCard.tsx
Obtención de límites efectivos:
// RPC function: get_business_effective_limitsconst { data: limits } = await supabase .rpc('get_business_effective_limits', { p_business_id: currentBusinessId });
// Retorna límites combinados (plan + custom overrides){ users: 3, // -1 = ilimitado monthly_invoices: 100, customers: 500, storage_gb: 10, // ... otros límites}Lógica de la función RPC:
CREATE OR REPLACE FUNCTION get_business_effective_limits(p_business_id UUID)RETURNS JSONB AS $$DECLARE v_limits JSONB; v_custom_limits JSONB;BEGIN -- 1. Obtener límites del plan SELECT sp.limits INTO v_limits FROM business_subscriptions bs JOIN subscription_plans sp ON sp.id = bs.plan_id WHERE bs.business_id = p_business_id AND bs.status IN ('active', 'trialing') ORDER BY bs.created_at DESC LIMIT 1;
-- 2. Obtener límites custom (si existen) SELECT custom_limits INTO v_custom_limits FROM business_subscriptions WHERE business_id = p_business_id AND custom_limits IS NOT NULL;
-- 3. Combinar (custom overrides plan) IF v_custom_limits IS NOT NULL THEN v_limits := v_limits || v_custom_limits; END IF;
RETURN v_limits;END;$$ LANGUAGE plpgsql;Cálculo de uso actual:
// Query en paralelo para optimizar rendimientoconst [invoices, customers, users, documents] = await Promise.all([ // Facturas del mes actual supabase .from('invoices') .select('id', { count: 'exact', head: true }) .eq('business_id', currentBusinessId) .gte('created_at', startOfMonth(new Date()).toISOString()),
// Clientes totales supabase .from('customers') .select('id', { count: 'exact', head: true }) .eq('business_id', currentBusinessId),
// Usuarios activos supabase .from('user_businesses') .select('id', { count: 'exact', head: true }) .eq('business_id', currentBusinessId),
// Documentos almacenados supabase .from('documents') .select('id', { count: 'exact', head: true }) .eq('business_id', currentBusinessId)]);
const usage = { invoices: invoices.count || 0, customers: customers.count || 0, users: users.count || 0, documents: documents.count || 0};Cálculo de porcentajes:
const percentage = limit === -1 ? 0 // Ilimitado → no mostrar barra : Math.min((current / limit) * 100, 100);
const variant = percentage >= 90 ? 'destructive' : percentage >= 75 ? 'warning' : 'default';Alertas automáticas:
// Si uso >= 90%, mostrar alerta{isAtLimit && ( <Alert variant="destructive"> <AlertCircle className="h-4 w-4" /> <AlertDescription> Has alcanzado el límite. Considera actualizar tu plan. </AlertDescription> </Alert>)}
// Si uso >= 75%, mostrar advertencia{isNearLimit && !isAtLimit && ( <Alert className="border-yellow-500/50 bg-yellow-500/10"> <AlertCircle className="h-4 w-4 text-yellow-600" /> <AlertDescription className="text-yellow-600"> Estás cerca del límite ({percentage.toFixed(0)}%) </AlertDescription> </Alert>)}Reseteo de límites mensuales:
Los límites mensuales se resetean automáticamente al inicio de cada período de facturación:
// Webhook: invoice.payment_succeededstripe.webhook.on('invoice.payment_succeeded', async (invoice) => { // Se considera inicio de nuevo período const newPeriodStart = new Date(invoice.period_start * 1000);
// NO se borran facturas, solo se ignoran las anteriores al nuevo período // El conteo se hace con filtro de fecha en el query});