Suscripción
Ruta:
/owner/settings/subscriptionGestiona tu plan de suscripción, métodos de pago, historial de facturación y límites de uso.
Vista general
Sección titulada «Vista general»El módulo de Suscripción te permite administrar completamente tu plan de Factux. Incluye tres secciones principales:
Pestañas: Uso | Historial | Facturación
Componentes principales:
| Componente | Descripción |
|---|---|
| Resumen de plan | Información del plan actual, estado y fecha de renovación |
| Uso de recursos | Visualización de límites y consumo actual |
| Historial de pagos | Registro de transacciones y facturas de suscripción |
| Información de facturación | Datos fiscales y métodos de pago |
Planes disponibles
Sección titulada «Planes disponibles»Factux ofrece tres niveles de suscripción con diferentes límites y características:
| Plan | Precio | Usuarios | Facturas/mes | Clientes | Almacenamiento |
|---|---|---|---|---|---|
| Free | 0 €/mes | 1 | 10 | 50 | 1 GB |
| Basic | 19 €/mes | 3 | 100 | 500 | 10 GB |
| Premium | 49 €/mes | Ilimitado | Ilimitado | Ilimitado | Ilimitado |
NOTA: Todos los planes incluyen período de prueba de 14 días sin necesidad de tarjeta de crédito.
Funciones
Sección titulada «Funciones»| Función | Descripción | Documentación |
|---|---|---|
| Ver plan actual | Consulta detalles del plan, estado y límites | Ver |
| Cambiar plan | Actualiza o reduce tu suscripción con prorrateo | Ver |
| Gestionar pago | Actualiza método de pago vía Stripe Portal | Ver |
| Ver historial | Consulta facturas y transacciones pasadas | Ver |
| Monitorear uso | Revisa consumo vs. límites del plan | Ver |
| Cancelar suscripción | Cancela al final del período actual | Ver |
Estados de suscripción
Sección titulada «Estados de suscripción» ┌─────────┐ │ Trialing│ └────┬────┘ │ Finaliza trial ┌────▼────┐ │ Active │─────────────┐ └────┬────┘ │ │ Falta pago │ ┌────▼────┐ ┌────▼────┐ │Past Due │ │Canceled │ └────┬────┘ │ FINAL │ │ └─────────┘ ┌────▼────┐ │Canceled │ │ FINAL │ └─────────┘Estados posibles:
| Estado | Descripción | Acceso al sistema |
|---|---|---|
trialing | Período de prueba activo | ✅ Completo |
active | Suscripción pagada y activa | ✅ Completo |
past_due | Pago pendiente | ⚠️ Limitado |
canceled | Suscripción cancelada | ❌ Bloqueado |
ALERTA: Las suscripciones en estado
past_duetienen 7 días para regularizar el pago antes de ser canceladas automáticamente.
Límites por plan
Sección titulada «Límites por plan»Los límites se aplican de forma automática según tu plan activo:
Free:
- 1 usuario máximo
- 10 facturas por mes
- 50 clientes totales
- 1 GB almacenamiento
Basic:
- 3 usuarios máximos
- 100 facturas por mes
- 500 clientes totales
- 10 GB almacenamiento
Premium:
- Usuarios ilimitados
- Facturas ilimitadas
- Clientes ilimitados
- Almacenamiento ilimitado
NOTA: Los límites mensuales se resetean al inicio de cada período de facturación.
Errores comunes
Sección titulada «Errores comunes»Error: “Datos de facturación incompletos”
Sección titulada «Error: “Datos de facturación incompletos”»Causa: Faltan campos obligatorios para crear suscripción en Stripe.
Solución:
- Ve a Configuración > Negocio
- Completa todos los campos obligatorios:
- CIF/NIF válido
- Dirección completa
- Código postal y ciudad
- Teléfono de contacto
Error: “No se pudo procesar el pago”
Sección titulada «Error: “No se pudo procesar el pago”»Causa: Problema con el método de pago configurado.
Solución:
- Haz clic en “Gestionar pago”
- Actualiza o añade un método de pago válido
- Verifica que la tarjeta tenga fondos suficientes
Error: “Ya tienes una suscripción activa”
Sección titulada «Error: “Ya tienes una suscripción activa”»Causa: Intentas crear una segunda suscripción activa.
Solución:
- Usa “Cambiar plan” en lugar de crear nueva suscripción
- Si el problema persiste, contacta a soporte
Referencia técnica
Sección titulada «Referencia técnica»Tablas de base de datos
| Tabla | Descripción | Columnas principales |
|---|---|---|
business_subscriptions | Suscripciones activas de negocios | business_id, plan_id, status, stripe_subscription_id, current_period_start, current_period_end, trial_end, cancel_at_period_end |
subscription_plans | Planes disponibles | name, slug, price, currency, billing_cycle, limits, features, stripe_product_id, stripe_price_id |
subscription_audit_log | Historial de cambios de plan | business_id, old_plan_id, new_plan_id, change_type, effective_date |
subscription_notifications | Notificaciones programadas | business_id, notification_type, scheduled_for, is_sent |
Relaciones:
business_subscriptions.business_id→businesses.idbusiness_subscriptions.plan_id→subscription_plans.id
Tipos TypeScript
// Hook useSubscriptionStatusexport interface SubscriptionStatus { hasSubscription: boolean; status: 'active' | 'trialing' | 'past_due' | 'canceled' | 'none'; planName?: string; planSlug?: string; planId?: string; plan?: { name: string; slug: string; limits?: Record<string, any>; }; currentPeriodStart?: Date; currentPeriodEnd?: Date; trialEnd?: Date; trialDaysRemaining?: number; isTrialing: boolean; isActive: boolean; cancelAtPeriodEnd: boolean; stripeCustomerId?: string; canAccessStripePortal: boolean;}
// Tabla subscription_plansinterface SubscriptionPlan { id: string; name: string; slug: string; price: number; currency: string; billing_cycle: 'monthly' | 'yearly'; limits: { users: number; // -1 = ilimitado monthly_invoices: number; customers: number; storage_gb: number; }; features: Record<string, boolean>; stripe_product_id: string | null; stripe_price_id: string | null; is_active: boolean; display_order: number;}
// Tabla business_subscriptionsinterface BusinessSubscription { id: string; business_id: string; plan_id: string; status: 'active' | 'trialing' | 'past_due' | 'canceled'; stripe_customer_id: string | null; stripe_subscription_id: string | null; current_period_start: string; current_period_end: string; trial_end: string | null; cancel_at_period_end: boolean; custom_limits: Record<string, any> | null; created_at: string; updated_at: string;}Edge Functions
create-checkout-session
Sección titulada «create-checkout-session»Propósito: Crea sesión de pago en Stripe o actualiza suscripción existente.
Endpoint: POST /functions/v1/create-checkout-session
Body:
{ business_id: string; plan_id: string; success_url?: string; cancel_url?: string;}Validaciones:
- Datos de facturación completos (CIF, dirección, teléfono)
- Business debe existir y estar activo
- Usuario debe tener permisos de owner
Respuestas:
// Caso 1: Nueva suscripción{ type: 'checkout', checkout_url: string}
// Caso 2: Cambio de plan con prorrateo{ type: 'plan_change', subscription_updated: true, message: string, invoice_url?: string}
// Caso 3: Error de validación{ error: string, validation: { errors: string[], warnings: string[], validated_fields: Record<string, boolean> }}stripe-webhook
Sección titulada «stripe-webhook»Propósito: Procesa eventos de Stripe (pagos, renovaciones, cancelaciones).
Eventos procesados:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedinvoice.payment_succeededinvoice.payment_failed
Acciones:
- Actualiza
business_subscriptions - Crea registros en
subscription_audit_log - Programa notificaciones en
subscription_notifications
cancel-subscription
Sección titulada «cancel-subscription»Propósito: Cancela suscripción al final del período actual.
Endpoint: POST /functions/v1/cancel-subscription
Body:
{ businessId: string;}Comportamiento:
- Marca
cancel_at_period_end = trueen Stripe - Actualiza registro en base de datos
- No cancela inmediatamente (acceso hasta fin de período)
get-proration-preview
Sección titulada «get-proration-preview»Propósito: Calcula prorrateo antes de cambio de plan.
Endpoint: POST /functions/v1/get-proration-preview
Body:
{ business_id: string; new_plan_id: string; user_id: string;}Respuesta:
{ proration: { credit_amount: number; // Crédito por tiempo no usado charge_amount: number; // Cargo por nuevo plan tax_amount: number; // Impuestos aplicables total_amount: number; // Total a pagar/reembolsar }}Componentes React principales
SubscriptionManagement
Sección titulada «SubscriptionManagement»Ruta: src/panels/owner/subscriptions/components/SubscriptionManagement.tsx
Descripción: Componente principal que organiza las tres pestañas de gestión.
Subcomponentes:
SubscriptionSummaryCard- Resumen del plan actualUsageLimitsCard- Visualización de límitesPaymentHistoryTable- Historial de pagosBillingInfoCard- Información de facturación
ChangePlanDialog
Sección titulada «ChangePlanDialog»Ruta: src/panels/owner/subscriptions/components/management/ChangePlanDialog.tsx
Props:
interface ChangePlanDialogProps { open: boolean; onOpenChange: (open: boolean) => void;}Funcionalidades:
- Muestra planes disponibles en grid
- Calcula prorrateo en tiempo real
- Valida datos de facturación antes de cambio
- Redirige a Stripe Checkout o actualiza directamente
Validaciones:
- No permite seleccionar plan actual
- Verifica datos de negocio completos
- Muestra preview de prorrateo
UsageLimitsCard
Sección titulada «UsageLimitsCard»Ruta: src/panels/owner/subscriptions/components/management/UsageLimitsCard.tsx
Descripción: Muestra barras de progreso para cada límite del plan.
Métricas monitoreadas:
- Usuarios activos
- Facturas del mes
- Clientes totales
- Almacenamiento usado
Alertas:
- ⚠️ Amarillo: 75-90% del límite
- 🔴 Rojo: 90-100% del límite
- ✅ Verde: menos de 75% del límite
Integración con Stripe
Configuración
Sección titulada «Configuración»Variables de entorno:
STRIPE_SECRET_KEY=sk_live_...STRIPE_WEBHOOK_SECRET=whsec_...STRIPE_PUBLISHABLE_KEY=pk_live_...Customer Portal
Sección titulada «Customer Portal»Factux usa Stripe Customer Portal para:
- Actualizar método de pago
- Ver historial de facturas
- Descargar recibos
- Gestionar datos de facturación
Acceso:
// Genera URL del portalconst { data } = await supabase.functions.invoke('create-portal-session', { body: { business_id: currentBusinessId }});
// Redirige al portalwindow.location.href = data.url;Webhooks
Sección titulada «Webhooks»Endpoint: https://[proyecto].supabase.co/functions/v1/stripe-webhook
Seguridad:
- Verifica firma de Stripe con
STRIPE_WEBHOOK_SECRET - Valida duplicados usando
stripe_event_id - Registra todos los eventos en logs
Eventos críticos:
// Pago exitoso'invoice.payment_succeeded' → status = 'active'
// Pago fallido'invoice.payment_failed' → status = 'past_due'
// Suscripción cancelada'customer.subscription.deleted' → status = 'canceled'Schemas y validaciones
Validación de datos de facturación
Sección titulada «Validación de datos de facturación»Función: validateBusinessBillingInfo
Ubicación: supabase/functions/_shared/customer-data-validator.ts
Campos validados:
interface ValidationResult { isValid: boolean; errors: string[]; warnings: string[]; validated_fields: { tax_id: boolean; legal_name: boolean; address: boolean; city: boolean; postal_code: boolean; country: boolean; phone: boolean; email: boolean; };}Reglas de validación:
-
CIF/NIF (tax_id):
- Formato: NIF (8 dígitos + letra), CIF (letra + 7 dígitos + control), NIE (X/Y/Z + 7 dígitos + letra)
- Validación de dígito de control
-
Teléfono:
- Formato: +34 seguido de 9 dígitos
- Prefijos válidos: 6XX, 7XX, 8XX, 9XX
-
Dirección:
- Mínimo 5 caracteres
- No puede estar vacía
-
Código postal:
- España: 5 dígitos (01XXX-52XXX)
- Otros países: mínimo 3 caracteres
RPC: get_business_effective_limits
Sección titulada «RPC: get_business_effective_limits»Descripción: Obtiene límites efectivos combinando plan + límites custom.
Uso:
const { data } = await supabase.rpc('get_business_effective_limits', { p_business_id: 'uuid-del-negocio'});
// Retorna:{ users: number, monthly_invoices: number, customers: number, storage_gb: number, // ... otros límites}Lógica:
- Lee
subscription_plans.limits - Aplica
business_subscriptions.custom_limitssi existen - Retorna objeto combinado con prioridad a custom
Flujos de usuario
Sección titulada «Flujos de usuario»Cambiar de plan Free a Premium
Sección titulada «Cambiar de plan Free a Premium»- Usuario en
/owner/settings/subscription - Clic en “Cambiar plan”
- Selecciona plan Premium
- Sistema calcula prorrateo (muestra preview)
- Clic en “Confirmar cambio”
- Si datos incompletos → muestra diálogo de validación
- Si datos OK → redirige a Stripe Checkout
- Usuario completa pago en Stripe
- Webhook actualiza suscripción a Premium
- Usuario es redirigido a
/subscription/success
Cancelar suscripción
Sección titulada «Cancelar suscripción»- Usuario en pestaña “Facturación”
- Clic en “Cancelar suscripción”
- Confirma en diálogo de advertencia
- Edge function marca
cancel_at_period_end = true - Usuario mantiene acceso hasta fin de período
- Al finalizar período, webhook cambia status a
canceled
Preguntas frecuentes
Sección titulada «Preguntas frecuentes»¿Puedo cambiar de plan en cualquier momento?
Sí, puedes cambiar entre planes en cualquier momento. El sistema aplicará prorrateo automático: se calcula el crédito por el tiempo no usado del plan actual y se carga la diferencia del nuevo plan.
¿Qué pasa si mi pago falla?
Si un pago falla, tu suscripción pasa a estado past_due. Tienes 7 días para actualizar tu método de pago. Durante este tiempo, tendrás acceso limitado al sistema. Si no se regulariza el pago, la suscripción será cancelada automáticamente.
¿Los límites se acumulan si no los uso?
No, los límites mensuales (como facturas/mes) se resetean al inicio de cada período de facturación. Los límites totales (como clientes) son acumulativos.
¿Puedo recuperar una suscripción cancelada?
Sí, puedes crear una nueva suscripción en cualquier momento desde el módulo de Suscripción. Sin embargo, se tratará como una nueva suscripción con un nuevo período de prueba si aplica.