Database Schema
JCV Fitness uses PostgreSQL (via Supabase) with Row Level Security (RLS) for data protection. All tables follow best practices with proper indexing, foreign keys, and audit trails.Schema Overview
Core Tables
profiles
Extends Supabaseauth.users with application-specific user data.
id: UUID, references auth.users (primary key)email: User email addressfull_name: Optional display namehas_active_subscription: Cached flag for quick access checkscurrent_plan: Current subscription tier (BASICO/PRO/PREMIUM)subscription_end_date: When current subscription expireshas_free_plan_used: Whether user has used their free trialfree_plan_expires_at: Free plan expiration dateactive_plan_id: Reference to currently active user_plancreated_at: Account creation timestampupdated_at: Last profile update
subscriptions
Tracks paid subscriptions with payment details.id: Unique subscription identifieruser_id: Owner of subscriptionplan_type: Subscription tier purchasedstatus: Current status (active/expired/cancelled)start_date: When subscription startedend_date: When subscription expires (start_date + duration)payment_provider: Payment gateway used (mercadopago/wompi)payment_reference: External payment ID from provideramount_paid: Amount in cents (e.g., 49900 = $49,900 COP)created_at: Subscription creation timestampupdated_at: Last modification timestamp
user_plans
Stores generated fitness and nutrition plans (freemium system).id: Plan identifieruser_id: Plan ownerplan_data: Complete plan as JSONB (workout + meal data)plan_type: ‘free’ (5 weeks) or ‘paid’ (1 year)created_at: Plan creation dateexpires_at: Plan expiration date (created_at + duration)is_active: Whether plan is currently activedownload_count: Number of PDF downloads (paid only)updated_at: Last modification
wizard_data
Stores raw wizard submissions before plan generation.id: Entry identifieruser_id: User who submitted wizarddata: Complete wizard state as JSONBcreated_at: Initial submission dateupdated_at: Last wizard update
plan_downloads
Tracks PDF downloads for security and rate limiting.id: Download record identifieruser_id: User who downloadedsubscription_id: Active subscription useddownload_token: Unique token for this downloadip_address: Client IP addressuser_agent: Browser user agentcreated_at: Download timestamp
Audit & Logging Tables
webhook_logs
Comprehensive audit trail for all payment webhooks.subscription_audit_log
Tracks all subscription lifecycle events.Database Functions
has_active_subscription
Check if user has any active subscription.get_active_subscription
Get details of user’s active subscription.expire_old_subscriptions
Cron job function to mark expired subscriptions.get_active_plan
Retrieve user’s current active plan with expiration info.create_user_plan
Create a new user plan (free or paid).can_create_plan
Check if user is allowed to create a new plan.Migration Files
Migrations are located in/supabase/migrations/:
- 001_initial_schema.sql - Core tables and RLS
- 002_user_plans.sql - Freemium system tables
Backup Strategy
Supabase Automatic Backups:- Daily snapshots (retained 7 days on free tier)
- Point-in-time recovery (paid plans only)
Related Documentation
- System Architecture - Overall system design
- Payment Integration - How payments update subscriptions
- Deployment Guide - Database setup procedures