Dashboard
Hola, JB 👋
¿Qué quieres revisar hoy?
🏢
Negocio
FinFlow · E-commerce
Entrar al dashboard →
🧑
Personal
Mis finanzas
Entrar al dashboard →

Ingresos · Costos · Meta Ads

Distribución de Gastos

Margen Bruto %

Pasivos por tipo

Flujo Neto Semanal

⚖️ Punto de Equilibrio

💸 Flujo de Caja y Liquidez

Últimos 7 días

Flujo Acumulado

Ingresos vs Egresos

Movimientos

FechaDescripciónTipoCategoríaMontoBalance

🔀 Flujo JB ↔ Negocio

👥 Clientes — CRM

🔌 ¿Cómo conectar Kommo / mi web para que los clientes entren solos?
Tu app lee la tabla clientes de Supabase. Para que Kommo (o tu web) los meta solos, usa Make/Zapier o un webhook que haga upsert por external_id:
POST {tu_url_supabase}/rest/v1/clientes?on_conflict=external_id
Header: apikey, Authorization: Bearer {anon_key}
Header: Prefer: resolution=merge-duplicates
Body: {"external_id":"kommo_12345","nombre":"Juan","telefono":"+593...","etapa":"Contactado","fuente":"kommo","valor_estimado":0}
El external_id evita duplicados: si Kommo manda el mismo lead otra vez, se actualiza en vez de crear otro. La etapa debe coincidir con una de tus etapas del pipeline. Cuando cambies un cliente de etapa en Kommo, tu automatización manda el nuevo etapa y aquí se mueve solo.

🛒 Ventas

FechaPedido #EstadoClienteProductosIngresosCostosMargenMeta Ads %Neto

📦 Inventario — Activos

ProductoTamaño / ColorSKUStockMi CostoP. MínimoP. NormalP. PromoMargen NormalValor StockEstado

Junta productos que ya tienes a un precio propio. Al vender uno, se descuenta el stock de cada producto que lo compone.

PackContieneCostoP. NormalP. PromoArmables hoy
FechaProductoUnidadesCosto unit.Total invertidoNota

💳 Pasivos y Deudas

NombreTipoTotalSaldoCuotaPróx. PagoInterés %

🏷️ Costos de Venta

⚙️ Valores por Defecto (aplicados automáticamente)
Estos valores se pre-rellenan al registrar una venta. Puedes cambiarlos por pedido.
FechaDescripciónTipoPedido #Monto

📣 Gastos Operativos

FechaDescripciónCategoríaFrecuenciaMonto

⚙️ Conexión Supabase

La conexión se define en el servidor (variables de entorno de Coolify) y no se puede cambiar desde acá. Así nadie puede apuntar la app a otro Supabase para robar tus credenciales al iniciar sesión.

-- Ejecuta este SQL en Supabase > SQL Editor: CREATE TABLE IF NOT EXISTS ventas ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, pedido_num text, productos jsonb DEFAULT '[]', total_ingresos numeric(12,2) DEFAULT 0, total_costos numeric(12,2) DEFAULT 0, margen_bruto numeric(12,2) DEFAULT 0, meta_ads_pct numeric(6,2) DEFAULT 0, meta_ads_monto numeric(12,2) DEFAULT 0, neto_real numeric(12,2) DEFAULT 0, origen text, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS inventario ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, producto text NOT NULL, sku text, unidades int DEFAULT 0, costo_unitario numeric(12,2) DEFAULT 0, precio_minimo numeric(12,2) DEFAULT 0, precio_normal numeric(12,2) DEFAULT 0, precio_promo numeric(12,2) DEFAULT 0, minimo int DEFAULT 5, es_pack boolean DEFAULT false, pack_items text, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS pasivos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nombre text NOT NULL, tipo text, total numeric(12,2) DEFAULT 0, saldo_pendiente numeric(12,2) DEFAULT 0, cuota numeric(12,2) DEFAULT 0, proximo_pago date, interes_anual numeric(6,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS costos_venta ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, descripcion text, tipo text, pedido_num text, monto numeric(12,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS gastos_operativos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, descripcion text NOT NULL, categoria text, frecuencia text, monto numeric(12,2) DEFAULT 0, cuenta_id uuid, dia_pago int, comision_pct numeric(6,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS cashflow ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, descripcion text, tipo text, categoria text, monto numeric(12,2) DEFAULT 0, balance numeric(12,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); -- ═══ Si ya tienes las tablas creadas, ejecuta estas migraciones ═══ ALTER TABLE cuentas ADD COLUMN IF NOT EXISTS ambito text DEFAULT 'personal'; ALTER TABLE movimientos_cuenta ADD COLUMN IF NOT EXISTS ambito text DEFAULT 'personal'; ALTER TABLE movimientos_cuenta ADD COLUMN IF NOT EXISTS pasivo_id uuid; ALTER TABLE movimientos_cuenta ADD COLUMN IF NOT EXISTS ingreso_id uuid; ALTER TABLE personal_gastos ADD COLUMN IF NOT EXISTS diferido boolean DEFAULT false; ALTER TABLE personal_gastos ADD COLUMN IF NOT EXISTS meses_diferido int; ALTER TABLE personal_gastos ADD COLUMN IF NOT EXISTS monto_total_diferido numeric(12,2); ALTER TABLE personal_gastos ADD COLUMN IF NOT EXISTS cuenta_id uuid; ALTER TABLE personal_gastos ADD COLUMN IF NOT EXISTS comision_pct numeric(6,2) DEFAULT 0; ALTER TABLE personal_gastos ADD COLUMN IF NOT EXISTS fecha_gasto date; ALTER TABLE personal_gastos_prof ADD COLUMN IF NOT EXISTS diferido boolean DEFAULT false; ALTER TABLE personal_gastos_prof ADD COLUMN IF NOT EXISTS meses_diferido int; ALTER TABLE personal_gastos_prof ADD COLUMN IF NOT EXISTS monto_total_diferido numeric(12,2); ALTER TABLE gastos_operativos ADD COLUMN IF NOT EXISTS diferido boolean DEFAULT false; ALTER TABLE gastos_operativos ADD COLUMN IF NOT EXISTS meses_diferido int; ALTER TABLE gastos_operativos ADD COLUMN IF NOT EXISTS monto_total_diferido numeric(12,2); -- ═══ TABLAS PERSONALES ═══ CREATE TABLE IF NOT EXISTS personal_ingresos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fuente text NOT NULL, tipo text, -- 'sueldo' | 'freelance' | 'arriendo' | 'otro' empresa text, frecuencia text, -- 'mensual' | 'quincenal' | 'semanal' | 'variable' dia_cobro int, -- día del mes (1-31) monto numeric(12,2) DEFAULT 0, activo boolean DEFAULT true, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS personal_gastos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nombre text NOT NULL, categoria text, -- 'Vivienda','Alimentación','Transporte','Suscripción trabajo','Suscripción entretenimiento','Salud','Ocio','Otro' subcategoria text, frecuencia text, -- 'mensual' | 'anual' | 'semanal' | 'variable' dia_pago int, -- día del mes fecha_gasto date, -- solo si frecuencia = 'ocasional' monto numeric(12,2) DEFAULT 0, activo boolean DEFAULT true, cuenta_id uuid, comision_pct numeric(6,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS personal_gastos_prof ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nombre text NOT NULL, categoria text, -- 'Software','Herramientas','Equipo','Internet / Teléfono','Capacitación','Otro' subcategoria text, frecuencia text, -- 'mensual' | 'anual' | 'semanal' | 'variable' | 'ocasional' dia_pago int, -- día del mes fecha_gasto date, -- solo si frecuencia = 'ocasional' monto numeric(12,2) DEFAULT 0, activo boolean DEFAULT true, cuenta_id uuid, comision_pct numeric(6,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS personal_deudas ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nombre text NOT NULL, tipo text, -- 'tarjeta_credito' | 'prestamo' | 'otro' total numeric(12,2) DEFAULT 0, saldo_pendiente numeric(12,2) DEFAULT 0, cuota numeric(12,2) DEFAULT 0, limite_credito numeric(12,2) DEFAULT 0, dia_pago int, interes_anual numeric(6,2) DEFAULT 0, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS cuentas ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nombre text NOT NULL, banco text, tipo text, -- 'efectivo' | 'corriente' | 'ahorro' | 'credito' ambito text DEFAULT 'personal', -- 'personal' | 'negocio' | 'ambas' balance_inicial numeric(12,2) DEFAULT 0, balance_actual numeric(12,2) DEFAULT 0, limite_credito numeric(12,2) DEFAULT 0, dia_corte int, -- para tarjetas: día de corte dia_pago int, -- para tarjetas: día de pago color text, -- color hex opcional activo boolean DEFAULT true, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS movimientos_cuenta ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, cuenta_id uuid REFERENCES cuentas(id) ON DELETE CASCADE, fecha date NOT NULL, tipo text NOT NULL, -- 'ingreso' | 'gasto' | 'abono' | 'transferencia' descripcion text, categoria text, monto numeric(12,2) DEFAULT 0, balance_despues numeric(12,2) DEFAULT 0, gasto_id uuid, -- referencia a personal_gastos si aplica ambito text DEFAULT 'personal', -- 'personal' | 'negocio' pasivo_id uuid, -- referencia a pasivos si aplica (abono a deuda) created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS inversiones_aportes ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, monto numeric(12,2) DEFAULT 0, -- dinero ingresado a la inversión comision numeric(12,2) DEFAULT 0, -- comisión cobrada en ese aporte nota text, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS inversiones_valoraciones ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, valor numeric(12,2) DEFAULT 0, -- valor total del portafolio ese día nota text, created_at timestamptz DEFAULT now() ); -- ═══ BITÁCORA TRADING ═══ CREATE TABLE IF NOT EXISTS trading_gastos ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, nombre text NOT NULL, categoria text, -- 'software' | 'deposito' | 'comision' | 'otro' frecuencia text, -- 'mensual' | 'unico' dia_pago int, -- día del mes, si frecuencia='mensual' fecha_gasto date, -- fecha, si frecuencia='unico' monto numeric(12,2) DEFAULT 0, cuenta_id uuid, activo boolean DEFAULT true, created_at timestamptz DEFAULT now() ); CREATE TABLE IF NOT EXISTS trading_trades ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, fecha date NOT NULL, instrumento text, direccion text, -- 'compra' | 'venta' modo text, -- 'test' | 'real' resultado numeric(12,2) DEFAULT 0, -- positivo=ganancia, negativo=pérdida notas text, created_at timestamptz DEFAULT now() ); -- ═══ POR COBRAR (consumos compartidos, ej. tarjeta de comida) ═══ CREATE TABLE IF NOT EXISTS cuentas_por_cobrar ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, persona text NOT NULL, descripcion text, monto numeric(12,2) DEFAULT 0, cuenta_id uuid, -- tarjeta/cuenta donde se hizo el consumo original fecha_consumo date, dia_cobro_estimado int, -- día del mes en que normalmente te pagan (ej. 19-22) estado text DEFAULT 'pendiente', -- 'pendiente' | 'cobrado' fecha_cobrado date, cuenta_cobro_id uuid, -- cuenta donde recibiste el pago gasto_id uuid, -- si nació desde un gasto personal dividido created_at timestamptz DEFAULT now() ); -- Si ya creaste la tabla antes de este cambio, ejecuta también: -- ALTER TABLE cuentas_por_cobrar ADD COLUMN IF NOT EXISTS gasto_id uuid; -- ═══ ENTRADAS DE INVENTARIO (llegadas de mercadería) ═══ -- Registra cada vez que llega producto: alimenta el pronóstico de demanda real -- (permite estimar cuántos días tuviste stock, no solo el promedio ciego). CREATE TABLE IF NOT EXISTS inventario_entradas ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, inventario_id uuid, -- SKU al que entró mercadería producto text, -- nombre snapshot (por si el SKU cambia después) unidades int DEFAULT 0, -- cuántas unidades llegaron costo_unitario numeric(12,2) DEFAULT 0, -- costo por unidad de esta compra fecha date NOT NULL, -- cuándo llegó la mercadería nota text, created_at timestamptz DEFAULT now() ); -- ═══ CLIENTES (CRM) ═══ -- Se llena manualmente O desde una fuente externa (Kommo, web, etc.). -- Para SINCRONIZAR desde Kommo: que tu automatización (Make/Zapier/Edge Function) -- haga UPSERT sobre external_id. Así el mismo cliente no se duplica. -- Ejemplo Supabase REST (upsert por external_id): -- POST /rest/v1/clientes?on_conflict=external_id -- Header: Prefer: resolution=merge-duplicates -- Body: {"external_id":"kommo_12345","nombre":"...","telefono":"...","etapa":"Contactado","fuente":"kommo"} CREATE TABLE IF NOT EXISTS clientes ( id uuid DEFAULT gen_random_uuid() PRIMARY KEY, external_id text UNIQUE, -- id del cliente en el sistema externo (Kommo lead id, etc.) para upsert sin duplicar nombre text NOT NULL, apellido text, cedula text, -- cédula / RUC / identificación telefono text, whatsapp text, email text, direccion text, ciudad text, provincia text, pais text, referencia text, -- referencia de ubicación / entrega etapa text, -- etapa del pipeline (nombre); NULL = sin etapa status text, -- estado del cliente (Active, etc.) fuente text DEFAULT 'manual', -- 'manual' | 'kommo' | 'web' | 'paradise' | 'effi' ... valor_estimado numeric(12,2) DEFAULT 0, -- valor potencial del cliente/negocio notas text, created_at timestamptz DEFAULT now(), updated_at timestamptz DEFAULT now() ); -- Si la tabla ya existía, corre también estos (idempotentes): ALTER TABLE clientes ADD COLUMN IF NOT EXISTS apellido text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS cedula text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS whatsapp text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS direccion text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS ciudad text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS provincia text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS pais text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS referencia text; ALTER TABLE clientes ADD COLUMN IF NOT EXISTS status text; -- Vincula ventas a un cliente (opcional): ALTER TABLE ventas ADD COLUMN IF NOT EXISTS cliente_id uuid;

🏧 Cuentas y Tarjetas

Consumos divididos (ej. tarjeta de comida) que otra persona te debe pagar.
Movimientos de:

🏛️ Tesorería del Negocio

⚠️ Estas son tus cuentas personales marcadas como "uso mixto". Los movimientos quedan etiquetados como uso negocio y afectan el balance de esa cuenta.
Movimientos:

📈 Inversiones

Evolución del valor

FechaValorNota
FechaMontoComisiónNetoNota

📉 Bitácora Trading

📚 Guía — esto es un camino largo
El trading es una de las profesiones más difíciles de dominar. La mayoría de quienes lo intentan tardan 1 a 3 años en operar con consistencia, practicando con disciplina — no es un camino rápido, y no pasa nada si tú también tardas.
🧪 Mientras un trade esté marcado como Test, es solo práctica: no es dinero real ni mide tu progreso real. Sirve para entender el patrón, nada más — no te exijas resultados ahí.
💰 Lo único que vale la pena vigilar de cerca es cuánto estás invirtiendo (arriba) frente a lo que tu cuenta real ha generado. Esa es tu única medida honesta de avance.

💼 Ingresos Profesionales

FuenteTipoEmpresa / ClienteFrecuenciaDía cobroMonto/mesActivo

🛍️ Gastos Personales

NombreCategoríaSubcategoríaFrecuenciaDía / FechaMonto/mesCuenta vinculadaActivo

🛠️ Gastos Profesionales

NombreCategoríaSubcategoríaFrecuenciaDía / FechaMonto/mesCuenta vinculadaActivo

🏦 Deudas Personales

NombreTipoSaldo Pend.Cuota/mesPagado este mesLímiteUso %Día pagoInterés %