Añade docs/estados-flujo.html: flujos de estado por canal
Referencia visual que separa las 4 dimensiones de estado (pipeline_stage, lead_estado, estado_wa, estado_conversacion del bot) y dibuja el flujo de formulario/WhatsApp/llamada sobre ellas, para decidir el modelado del estado de conversación de Luisa. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
207
docs/estados-flujo.html
Normal file
207
docs/estados-flujo.html
Normal file
@@ -0,0 +1,207 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Reformix — Flujos de estado por canal</title>
|
||||
<style>
|
||||
:root{
|
||||
--pipe:#0066ff; --pipe-bg:#e8f0fe;
|
||||
--crm:#0f7a52; --crm-bg:#e6f4ee;
|
||||
--wa:#0891b2; --wa-bg:#e0f4f8;
|
||||
--bot:#b45309; --bot-bg:#fbf0e0;
|
||||
--bad:#dc2626; --bad-bg:#fdeaea;
|
||||
--ink:#18181b; --muted:#71717a; --line:#e4e4e7; --card:#fff; --bg:#f4f4f5;
|
||||
--font:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
|
||||
}
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font);line-height:1.5}
|
||||
.wrap{max-width:1280px;margin:0 auto;padding:28px 20px 80px}
|
||||
h1{font-size:26px;font-weight:800;letter-spacing:-.4px;margin:0 0 4px}
|
||||
.sub{color:var(--muted);margin:0 0 22px;font-size:14px}
|
||||
h2{font-size:15px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);margin:34px 0 12px;font-weight:700}
|
||||
|
||||
/* Leyenda de dimensiones */
|
||||
.dims{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
|
||||
.dim{background:var(--card);border:1px solid var(--line);border-left-width:5px;border-radius:10px;padding:12px 14px}
|
||||
.dim h3{margin:0 0 4px;font-size:13px;font-family:ui-monospace,monospace}
|
||||
.dim p{margin:0 0 8px;font-size:12px;color:var(--muted)}
|
||||
.dim .vals{display:flex;flex-wrap:wrap;gap:4px}
|
||||
.pip{border-left-color:var(--pipe)} .pip h3{color:var(--pipe)}
|
||||
.crm{border-left-color:var(--crm)} .crm h3{color:var(--crm)}
|
||||
.waL{border-left-color:var(--wa)} .waL h3{color:var(--wa)}
|
||||
.botL{border-left-color:var(--bot)} .botL h3{color:var(--bot)}
|
||||
.chip{display:inline-block;font-size:10.5px;font-family:ui-monospace,monospace;padding:2px 7px;border-radius:99px;border:1px solid var(--line);background:#fafafa;color:#3f3f46;white-space:nowrap}
|
||||
.chip.p{background:var(--pipe-bg);border-color:#cdddff;color:#1d4ed8}
|
||||
.chip.c{background:var(--crm-bg);border-color:#bfe3d2;color:#0f7a52}
|
||||
.chip.w{background:var(--wa-bg);border-color:#bfe6ef;color:#0e7490}
|
||||
.chip.b{background:var(--bot-bg);border-color:#f0d9b5;color:#b45309}
|
||||
.chip.x{background:var(--bad-bg);border-color:#f5c2c2;color:#dc2626}
|
||||
|
||||
/* Columnas de canal */
|
||||
.cols{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;align-items:start}
|
||||
.col{background:var(--card);border:1px solid var(--line);border-radius:12px;overflow:hidden}
|
||||
.col > .head{padding:12px 16px;font-weight:700;font-size:15px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:8px}
|
||||
.col.form > .head{background:#f5f3ff} .col.wa > .head{background:var(--wa-bg)} .col.call > .head{background:#fff7ed}
|
||||
.steps{padding:14px 16px;display:flex;flex-direction:column;gap:0}
|
||||
.step{position:relative;padding:10px 0 14px}
|
||||
.step .t{font-size:13.5px;font-weight:600}
|
||||
.step .d{font-size:12px;color:var(--muted);margin:2px 0 6px}
|
||||
.step .tags{display:flex;flex-wrap:wrap;gap:4px}
|
||||
.arrow{height:16px;display:flex;justify-content:center;color:#a1a1aa;font-size:13px}
|
||||
.branch{border:1px dashed var(--line);border-radius:8px;padding:8px 10px;margin-top:6px;background:#fafafa}
|
||||
.branch .t{font-size:12.5px;font-weight:600}
|
||||
.dot{width:8px;height:8px;border-radius:99px;display:inline-block}
|
||||
|
||||
.conv{background:var(--bot-bg);border:1px solid #f0d9b5;border-radius:8px;padding:8px 10px;margin-top:6px}
|
||||
.conv .t{font-size:12px;font-weight:700;color:var(--bot);margin-bottom:4px}
|
||||
.conv .flow{font-family:ui-monospace,monospace;font-size:11px;color:#92400e;line-height:1.7}
|
||||
|
||||
.converge{margin-top:18px;background:var(--card);border:1px solid var(--line);border-radius:12px;padding:16px}
|
||||
.converge .row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:13px}
|
||||
.converge .b{font-weight:700}
|
||||
|
||||
.note{background:#fffbeb;border:1px solid #fde68a;border-radius:10px;padding:14px 16px;margin-top:14px;font-size:13.5px}
|
||||
.note h3{margin:0 0 8px;font-size:14px}
|
||||
.note ul{margin:6px 0 0;padding-left:18px} .note li{margin:4px 0}
|
||||
.rec{background:#ecfdf5;border:1px solid #a7f3d0}
|
||||
table{width:100%;border-collapse:collapse;font-size:12.5px;margin-top:6px}
|
||||
th,td{text-align:left;padding:6px 8px;border-bottom:1px solid var(--line);vertical-align:top}
|
||||
th{color:var(--muted);font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.5px}
|
||||
code{font-family:ui-monospace,monospace;background:#f4f4f5;padding:1px 5px;border-radius:5px;font-size:11.5px}
|
||||
@media(max-width:980px){.dims{grid-template-columns:repeat(2,1fr)}.cols{grid-template-columns:1fr}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<h1>Reformix — Flujos de estado por canal</h1>
|
||||
<p class="sub">El lío viene de mezclar varias "estados" que en realidad son <b>4 dimensiones independientes</b>. Aquí están separadas y el flujo de cada canal sobre ellas. DB única; el lead se crea siempre en el form web.</p>
|
||||
|
||||
<h2>1 · Las 4 dimensiones de estado (ortogonales)</h2>
|
||||
<div class="dims">
|
||||
<div class="dim pip">
|
||||
<h3>pipeline_stage</h3>
|
||||
<p>Avance TÉCNICO en el funnel. Lo comparten los 3 canales y es lo que ve el panel. <b>Lo gestiona la app/EP, no el bot.</b></p>
|
||||
<div class="vals">
|
||||
<span class="chip p">form_completado</span><span class="chip p">fotos_subidas</span><span class="chip p">prellamada_enviada</span><span class="chip p">llamada_completada</span><span class="chip p">render_generado</span><span class="chip p">presupuesto_generado</span><span class="chip p">whatsapp_entregado</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dim crm">
|
||||
<h3>lead_estado</h3>
|
||||
<p>Estado COMERCIAL / CRM. Lo lleva el reformista (y algún automatismo). Independiente del canal.</p>
|
||||
<div class="vals">
|
||||
<span class="chip c">nuevo</span><span class="chip c">contactado</span><span class="chip c">visita_agendada</span><span class="chip c">presupuesto_enviado</span><span class="chip c">ganado</span><span class="chip x">perdido</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dim waL">
|
||||
<h3>estado_wa</h3>
|
||||
<p>SOLO entrega del último mensaje de WhatsApp (técnico, por-mensaje). <b>No</b> es "en qué punto va la conversación".</p>
|
||||
<div class="vals">
|
||||
<span class="chip w">sin_enviar</span><span class="chip w">enviado</span><span class="chip w">entregado</span><span class="chip w">leido</span><span class="chip x">fallido</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dim botL">
|
||||
<h3>estado_conversacion <span style="color:var(--bad)">(NO existe aún)</span></h3>
|
||||
<p>En qué paso va Luisa en la cualificación. Hoy vive solo dentro del bot. <b>La decisión es si lo persistimos.</b></p>
|
||||
<div class="vals">
|
||||
<span class="chip b">apertura</span><span class="chip b">espacio</span><span class="chip b">tamaño</span><span class="chip b">estilo</span><span class="chip b">urgencia</span><span class="chip b">presupuesto</span><span class="chip b">pide_fotos</span><span class="chip b">completado</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>2 · Flujo de cada canal sobre esas dimensiones</h2>
|
||||
<div class="cols">
|
||||
|
||||
<!-- FORMULARIO -->
|
||||
<div class="col form">
|
||||
<div class="head">📝 Formulario web</div>
|
||||
<div class="steps">
|
||||
<div class="step"><div class="t">Cliente deja datos (crearLead)</div><div class="d">nombre · tel · email · opt-ins</div><div class="tags"><span class="chip p">form_completado</span><span class="chip c">nuevo</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Rellena por zonas + sube fotos</div><div class="d">guardarDetallesYFotos → lead_fotos (antes) + lead_notas</div><div class="tags"><span class="chip p">fotos_subidas</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Presupuesto orientativo al instante</div><div class="d">motor de presupuesto + señal perfilCompleto</div><div class="tags"><span class="chip p">presupuesto_generado</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Converge en calificación →</div><div class="tags"><span class="chip c">contactado</span></div></div>
|
||||
<div class="conv"><div class="t">No usa</div><div class="flow">estado_wa · estado_conversacion (no hay chat)</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- WHATSAPP -->
|
||||
<div class="col wa">
|
||||
<div class="head">💬 WhatsApp — Luisa</div>
|
||||
<div class="steps">
|
||||
<div class="step"><div class="t">Lead ya existe (del form) → elige WhatsApp</div><div class="d">app emite WHATSAPP_START con leadId</div><div class="tags"><span class="chip p">form_completado</span><span class="chip c">nuevo</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Bot escribe el 1er mensaje</div><div class="d">entrega del mensaje (no la conversación)</div><div class="tags"><span class="chip w">sin_enviar→enviado→entregado→leido</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Luisa cualifica (conversación)</div><div class="d">guarda cada turno en conversacion_whatsapp + extrae a leads</div>
|
||||
<div class="conv"><div class="t">estado_conversacion (bot)</div><div class="flow">apertura → espacio → tamaño → estilo → urgencia → presupuesto</div></div>
|
||||
</div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">¿Viable? (≥ 5000€)</div>
|
||||
<div class="branch"><div class="t">No → <span class="chip x">perdido</span> (no_viable, descartado)</div></div>
|
||||
<div class="branch"><div class="t">Sí → pide fotos por WA</div><div class="tags" style="margin-top:6px"><span class="chip b">pide_fotos</span></div></div>
|
||||
</div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Fotos recibidas → EP ingesta</div><div class="d">lead_fotos (antes) + worker analiza</div><div class="tags"><span class="chip p">fotos_subidas</span><span class="chip b">completado</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Converge en calificación →</div><div class="tags"><span class="chip c">contactado</span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LLAMADA -->
|
||||
<div class="col call">
|
||||
<div class="head">📞 Llamada</div>
|
||||
<div class="steps">
|
||||
<div class="step"><div class="t">Lead ya existe (del form) → pide llamada</div><div class="d">ahora / programar</div><div class="tags"><span class="chip p">prellamada_enviada</span><span class="chip c">nuevo</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Bot de llamada (externo)</div><div class="d">registra intento en intentos_contacto</div><div class="tags"><span class="chip p">llamada_completada</span></div>
|
||||
<div class="branch"><div class="t">resultado_contacto</div><div class="tags" style="margin-top:6px"><span class="chip">exitoso</span><span class="chip">no_contesta</span><span class="chip">ocupado</span><span class="chip x">rechaza</span></div></div>
|
||||
</div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Pide fotos por WA o email→formulario</div><div class="d">leads.fotos_solicitadas_at</div><div class="tags"><span class="chip w">enviado</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Fotos recibidas → EP ingesta</div><div class="d">lead_fotos (antes) + worker</div><div class="tags"><span class="chip p">fotos_subidas</span></div></div>
|
||||
<div class="arrow">↓</div>
|
||||
<div class="step"><div class="t">Converge en calificación →</div><div class="tags"><span class="chip c">contactado</span></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CONVERGENCIA -->
|
||||
<h2>3 · Convergencia (los 3 canales acaban igual)</h2>
|
||||
<div class="converge">
|
||||
<div class="row">
|
||||
<span class="chip c">Calificación</span><span>lead_calificacion (score + A/B/C/D)</span> <span style="color:#a1a1aa">→</span>
|
||||
<span class="chip c">visita_agendada</span> <span style="color:#a1a1aa">→</span>
|
||||
<span class="chip p">render_generado</span><span class="chip p">presupuesto_generado</span> <span style="color:#a1a1aa">→</span>
|
||||
<span class="chip p">whatsapp_entregado</span><span class="chip c">presupuesto_enviado</span> <span style="color:#a1a1aa">→</span>
|
||||
<span class="chip c">ganado</span> / <span class="chip x">perdido</span> <span style="color:#a1a1aa">→</span> testimonio
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DECISIÓN -->
|
||||
<h2>4 · La decisión a tomar</h2>
|
||||
<div class="note">
|
||||
<h3>¿WhatsApp necesita "otros estados"? Sí, pero ojo a CUÁL:</h3>
|
||||
<ul>
|
||||
<li><b>estado_wa</b> (ya lo tenemos): es solo si el mensaje llegó/se leyó. Útil pero de bajo nivel.</li>
|
||||
<li><b>estado_conversacion (Luisa)</b>: <u>esto es lo que de verdad falta</u> si queremos saber "por qué paso va el chat" y poder retomarlo si se corta. Hoy NO está en la DB.</li>
|
||||
<li>El <b>diagrama del compañero</b> ponía <code>estado_wa = nuevo</code> → mezcla los dos conceptos. <code>nuevo</code> no es entrega de mensaje, es "conversación sin empezar".</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="note rec">
|
||||
<h3>Mi recomendación</h3>
|
||||
<ul>
|
||||
<li><b>pipeline_stage</b> = única fuente del avance del lead (lo pinta el panel). Lo escribe la app/EP. <b>El bot NO lo toca.</b></li>
|
||||
<li><b>lead_estado</b> = comercial, lo lleva el reformista.</li>
|
||||
<li><b>estado_wa</b> = déjalo solo para entrega de mensaje (sin_enviar…leido). No metas "nuevo" ahí.</li>
|
||||
<li><b>estado_conversacion del bot</b>: 2 opciones —
|
||||
<br>(a) vive SOLO dentro del bot/n8n (no lo persistimos en nuestra DB) → más simple, suficiente para la demo;
|
||||
<br>(b) lo persistimos como columna nueva <code>leads.bot_step</code> (o tabla) si queremos verlo en el panel / retomar conversaciones. <b>← esto es lo que hay que decidir.</b></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user