# Mariachis.co — Documentación del Proyecto

> Última actualización: 2026-05-22
> Estado: en desarrollo activo

---

## Índice

1. [¿Qué es Mariachis.co?](#1-qué-es-mariachisco)
2. [Stack tecnológico](#2-stack-tecnológico)
3. [Arquitectura de la aplicación](#3-arquitectura-de-la-aplicación)
4. [Roles y portales](#4-roles-y-portales)
5. [Modelos de datos clave](#5-modelos-de-datos-clave)
6. [Flujo actual de registro y activación (mariachi)](#6-flujo-actual-de-registro-y-activación-mariachi)
7. [Flujo de anuncios (listings)](#7-flujo-de-anuncios-listings)
8. [Sistema de planes y pagos](#8-sistema-de-planes-y-pagos)
9. [Pasarela de pagos: ePayco](#9-pasarela-de-pagos-epayco)
10. [Integraciones externas](#10-integraciones-externas)
11. [Problemas identificados](#11-problemas-identificados)
12. [Análisis del modelo de negocio](#12-análisis-del-modelo-de-negocio)
13. [Propuesta de pricing](#13-propuesta-de-pricing)
14. [Roadmap de cambios](#14-roadmap-de-cambios)

---

## 1. ¿Qué es Mariachis.co?

**Mariachis.co** es una plataforma de marketplace que conecta **músicos y grupos de mariachi** con **clientes** que buscan contratar sus servicios en Colombia. Funciona como un directorio de anuncios pagos donde:

- Los **mariachis (partners)** publican sus servicios, fotos, videos, precios y áreas de cobertura.
- Los **clientes** buscan por ciudad, tipo de evento y presupuesto, contactan al mariachi directamente vía WhatsApp o formulario, y dejan reseñas.
- El **dueño de la plataforma** cobra a los mariachis una tarifa por tener su cuenta activa y por publicar/mantener sus anuncios visibles.

**Analogías de referencia:**
- Similar a OLX o Marketplace en el modelo de anuncios con vencimiento.
- Similar a Google/Facebook Ads en el concepto de visibilidad pagada.
- Similar a Booking.com / Airbnb en el rol de intermediario que cobra al proveedor, no al consumidor.

---

## 2. Stack tecnológico

| Capa | Tecnología | Versión |
|---|---|---|
| Backend | Laravel | ^12.0 |
| PHP | PHP | ^8.2 |
| Base de datos | MySQL | 8.0+ |
| Frontend build | Vite | 6.4.1 |
| CSS | Bootstrap + Tailwind CSS | 5.3.6 / ^3.4.17 |
| Template admin | Vuexy (Bootstrap) | 3.0.0 |
| JS | jQuery + Alpine.js (implícito) | 3.7.1 |
| Gráficos | ApexCharts | 4.2.0 |
| Mapas | Leaflet + Mapbox GL | 1.9.4 |
| Búsqueda | Algolia Autocomplete | 1.19.6 |
| Alertas | SweetAlert2 | 11.26.22 |
| Pagos | ePayco | API v2 |
| Login social | Google + Facebook via Socialite | ^5.25 |
| Monitoreo errores | Sentry | ^4.22 |
| SEO/Shopping | Google Merchant Center | API v1 |
| Analytics | GA4 + GTM | — |

---

## 3. Arquitectura de la aplicación

### Estructura de directorios

```
app/
├── Http/
│   ├── Controllers/
│   │   ├── Admin/         # Panel de administración
│   │   ├── Mariachi/      # Portal partner (mariachi)
│   │   ├── Client/        # Panel del cliente
│   │   ├── Front/         # Sitio público
│   │   └── Auth/          # Autenticación
│   └── Middleware/        # 8 middlewares personalizados
├── Models/                # 53 modelos Eloquent
├── Services/              # 28 servicios de negocio
├── Notifications/         # Emails y notificaciones
└── Helpers/

routes/
├── public.php             # Dominio principal (mariachis.co)
├── partner.php            # Subdominio partner (partner.mariachis.co)
├── admin.php              # Subdominio admin (admin.mariachis.co)
└── console.php            # Comandos artisan

resources/
├── views/
│   ├── layouts/           # Layouts base por portal
│   ├── content/           # Vistas por sección
│   ├── components/        # Componentes Blade reutilizables
│   └── emails/            # Plantillas de email
└── js/ / css/             # Assets compilados con Vite
```

### Arquitectura multi-dominio

La aplicación usa tres dominios, cada uno con su propio conjunto de rutas, sesiones y middleware:

| Dominio (local) | Dominio (producción) | Portal |
|---|---|---|
| `localhost` | `mariachis.co` | Sitio público + clientes |
| `partner.localhost` | `partner.mariachis.co` | Panel de mariachis |
| `admin.localhost` | `admin.mariachis.co` | Panel de administración |

Las sesiones están separadas por dominio. Un mariachi logueado en `partner.*` no tiene sesión en `mariachis.co`.

---

## 4. Roles y portales

### Roles del sistema (`User::role`)

| Rol | Acceso | Descripción |
|---|---|---|
| `admin` | `admin.*` | Control total del sistema |
| `staff` | `admin.*` | Soporte y moderación (sin acceso a config crítica) |
| `mariachi` | `partner.*` | Artista/grupo que publica anuncios |
| `client` | `mariachis.co` | Usuario que busca y contacta mariachis |

### Estados de usuario (`User::status`)

| Estado | Significado |
|---|---|
| `active` | Cuenta activa, acceso completo |
| `inactive` | Cuenta desactivada manualmente |
| `pending_activation` | Registrado pero sin pago de activación |

---

## 5. Modelos de datos clave

### Árbol de relaciones principal

```
User (id, role, status)
├── hasOne  → MariachiProfile
│             ├── hasMany → MariachiListing (anuncios)
│             │             ├── hasMany → ListingPayment (pagos)
│             │             ├── hasMany → MariachiListingPhoto
│             │             ├── hasMany → MariachiListingVideo
│             │             ├── hasMany → MariachiListingFaq
│             │             ├── hasMany → QuoteConversation (cotizaciones)
│             │             ├── hasMany → MariachiReview (reseñas)
│             │             └── belongsToMany → EventType, ServiceType, GroupSizeOption, BudgetRange
│             ├── hasMany → AccountActivationPayment
│             ├── hasMany → ProfileVerificationPayment
│             └── hasMany → MariachiPhoto, MariachiVideo
│
└── hasOne  → ClientProfile
              ├── hasMany → QuoteConversation
              ├── hasMany → ClientFavorite (listings favoritos)
              └── hasMany → ClientRecentView
```

### Modelos del sistema de monetización

| Modelo | Tabla | Descripción |
|---|---|---|
| `Plan` | `plans` | Planes de anuncio (Basic, Pro, Premium) |
| `PlanEntitlement` | `plan_entitlements` | Derechos/capacidades de cada plan |
| `ListingPayment` | `listing_payments` | Pagos por publicar un anuncio |
| `AccountActivationPlan` | `account_activation_plans` | Plan de activación inicial de cuenta |
| `AccountActivationPayment` | `account_activation_payments` | Pago de activación de cuenta |
| `ProfileVerificationPlan` | `profile_verification_plans` | Plan de verificación de identidad |
| `ProfileVerificationPayment` | `profile_verification_payments` | Pago de verificación |

---

## 6. Flujo actual de registro y activación (mariachi)

### Flujo actual (problemático)

```
/signup (datos básicos)
    ↓
Crear User con status = pending_activation
    ↓
/signup/activar/{user}/{token}  ← ACCESO AL PANEL BLOQUEADO HASTA AQUÍ
    ↓
Seleccionar plan de activación → Checkout ePayco
    ↓
Webhook aprueba → status = active
    ↓
Acceso al panel partner
```

**Problema:** El mariachi no puede ver absolutamente nada del panel hasta pagar. Esto genera fricción y desconfianza. No puede evaluar si la plataforma vale la pena antes de invertir.

### Flujo propuesto (nuevo)

```
/signup (datos básicos)
    ↓
Crear User con status = pending_activation
    ↓
ACCESO AL PANEL (con cuenta inactiva, modo exploración)
    ↓ (banner visible en todas las páginas)
┌─────────────────────────────────────────────────────┐
│  ⚠️  Tu cuenta está inactiva                         │
│  Para publicar tus anuncios activa tu cuenta por    │
│  $19.800 COP. Tienes 14 días antes de que tu        │
│  cuenta sea eliminada.   [Activar ahora →]          │
└─────────────────────────────────────────────────────┘
    ↓ (si pasan 14 días sin pagar)
Cuenta desactivada + eliminada automáticamente (job programado)
    ↓ (si paga)
status = active → puede crear y publicar anuncios
```

**Cambios de código necesarios para este flujo:**

1. **Middleware `EnsureUserHasRole`**: permitir acceso al panel con `status = pending_activation`, no solo `active`.
2. **`MariachiRegistrationController`**: quitar el redirect forzado al formulario de activación después del registro.
3. **Layout `partner.blade.php`**: agregar el banner de cuenta inactiva (visible solo si `status = pending_activation`).
4. **Controladores del panel**: bloquear solo las acciones de creación de anuncios y publicación cuando `pending_activation`, no todo el panel.
5. **Job `DeleteUnactivatedAccounts`**: crear un job programado que revise diariamente si han pasado 14 días desde el registro y la cuenta sigue en `pending_activation`, y la elimine.
6. **Campo en `users`**: agregar `activation_deadline_at` (fecha registro + 14 días) para el job.

---

## 7. Flujo de anuncios (listings)

### Ciclo de vida de un anuncio

```
DRAFT
  → (completa información) → AWAITING_PLAN
  → (selecciona plan) → AWAITING_PAYMENT
  → (paga con ePayco) → en revisión admin (review_status = pending)
  → (admin aprueba) → ACTIVE ✅
  → (vence expires_at) → EXPIRED ❌
  → (renueva pago) → ACTIVE ✅
  → (pausa manual) → PAUSED ⏸
  → (admin o dueño elimina) → REMOVED 🗑
```

### Visibilidad pública

Un anuncio es visible en el sitio público **solo si cumple TODAS estas condiciones**:

```php
status = 'active'
is_active = true
review_status = 'approved'
payment_status = 'approved'
deleted_at = null
expires_at > now()
user.status = 'active'
```

### Comportamiento cuando un anuncio expira o se oculta

Cuando un anuncio vence o se pausa, el sistema **no deja una página en blanco**. En su lugar, redirige a una landing con otros mariachis disponibles en la misma ciudad. Esto evita perder el tráfico orgánico de Google que ya encontró esa URL.

---

## 8. Sistema de planes y pagos

### Planes de anuncio actuales (base de datos)

| Código | Nombre | Precio/mes | listing_limit |
|---|---|---|---|
| `basic` | Plan Básico | $29.900 COP | — |
| `pro` | Plan Pro | $59.900 COP | — |
| `premium` | Plan Premium | $99.900 COP | — |

> ⚠️ **Problema:** `listing_limit = 0` en todos los planes. Los entitlements específicos de cada plan (fotos, videos, visibilidad en home, badge, etc.) están definidos en la tabla `plan_entitlements` pero deben revisarse y completarse.

### Plan de activación de cuenta

| Código | Nombre | Monto | Tipo |
|---|---|---|---|
| `ACTIVACION_CUENTA` | Activación de cuenta | $18.900 COP | one_time |

> El dueño mencionó $19.800. Ajustar en admin panel o directamente en BD según decisión final.

### ¿Qué entitlements existen por plan?

Los entitlements se guardan en `plan_entitlements` con clave/valor flexible. Las capacidades que el sistema reconoce son:

| Entitlement key | Descripción |
|---|---|
| `max_photos` | Máximo de fotos por anuncio |
| `max_videos` | Máximo de videos por anuncio |
| `show_whatsapp` | Mostrar botón WhatsApp en el anuncio |
| `show_phone` | Mostrar teléfono en el anuncio |
| `priority_level` | Posición en el ranking de búsqueda (0=normal) |
| `allows_verification` | Puede solicitar badge de perfil verificado |
| `allows_featured_city` | Anuncio destacado en la portada de su ciudad |
| `allows_featured_home` | Anuncio destacado en el home principal |
| `has_premium_badge` | Muestra badge "Pro" o "Premium" en la tarjeta |
| `has_advanced_stats` | Acceso a métricas avanzadas |

---

## 9. Pasarela de pagos: ePayco

ePayco es la pasarela principal y está integrada para tres tipos de cobro:

| Tipo | Constante | Cuándo se usa |
|---|---|---|
| Activación de cuenta | `TYPE_ACTIVATION` | Mariachi paga $19.800 para activar su cuenta |
| Pago de anuncio | `TYPE_LISTING` | Mariachi paga para publicar/renovar un anuncio |
| Verificación de perfil | `TYPE_VERIFICATION` | Mariachi paga para obtener badge verificado |

### Flujo de pago

```
1. Controller llama EpaycoPaymentFlowService::begin*Checkout()
2. Se crea el registro *Payment con status='pending' y checkout_reference único
3. Frontend abre modal/redirect a checkout.epayco.co
4. Usuario paga
5. ePayco llama webhook: POST /pagos/epayco/webhook
6. EpaycoPaymentController::webhook() valida firma HMAC
7. Llama EpaycoPaymentFlowService::syncPaymentFromTransaction()
8. Actualiza status → 'approved' o 'rejected'
9. Si approved: activa listing / activa cuenta / activa verificación
```

### Variables de entorno necesarias

```
EPAYCO_ENVIRONMENT=sandbox        # cambiar a production en producción
EPAYCO_PUBLIC_KEY=
EPAYCO_PRIVATE_KEY=
EPAYCO_CUSTOMER_ID=
EPAYCO_P_KEY=
```

---

## 10. Integraciones externas

| Integración | Para qué sirve | Variables env |
|---|---|---|
| Google Maps API | Autocompletar dirección en anuncios, mapa de cobertura | `GOOGLE_MAPS_API_KEY` |
| Google Login (Socialite) | Login sin contraseña para clientes | `GOOGLE_CLIENT_ID/SECRET` |
| Facebook Login (Socialite) | Login sin contraseña para clientes | `FACEBOOK_CLIENT_ID/APP_SECRET` |
| Google Merchant Center | Sincronizar anuncios activos al feed de Shopping | `GOOGLE_MERCHANT_ACCOUNT_ID` |
| Google Analytics 4 | Tracking de visitas y conversiones | `TRACKING_GA4_MEASUREMENT_ID` |
| Google Tag Manager | Contenedor de tracking | `TRACKING_GTM_CONTAINER_ID` |
| Sentry | Monitoreo de errores en producción | `SENTRY_LARAVEL_DSN` |
| ePayco | Pasarela de pagos (COP, Colombia) | Ver sección 9 |

---

## 11. Problemas identificados

### P1 — Flujo de activación genera fricción (CRÍTICO)

**Problema:** Los mariachis son enviados directamente al checkout de pago antes de poder explorar la plataforma. No pueden evaluar el valor antes de pagar.

**Impacto:** Alta tasa de abandono en el registro. Los mariachis no confían en pagar sin ver qué obtienen.

**Solución:** Ver sección 6 — flujo propuesto con banner de cuenta inactiva y 14 días de gracia.

### P2 — Entitlements de planes incompletos o vacíos

**Problema:** Los planes `basic`, `pro` y `premium` existen en la tabla `plans`, pero `listing_limit = 0` y no hay entitlements cargados que diferencien qué puede hacer cada plan.

**Impacto:** No hay una diferencia real entre pagar el plan básico y el premium. El sistema no puede hacer cumplir los límites.

**Solución:** Definir la tabla de beneficios por plan (ver sección 13) y cargar los entitlements correctos vía seeder o panel admin.

### P3 — Precio de activación inconsistente

**Problema:** La BD tiene $18.900 pero el dueño menciona $19.800.

**Solución:** Actualizar en el panel admin o en la migración seed a $19.800.

### P4 — No existe job de eliminación de cuentas no activadas

**Problema:** No hay un proceso automático que elimine cuentas con `pending_activation` después de 14 días.

**Solución:** Crear `app/Console/Commands/PurgeUnactivatedAccounts.php` + schedulear en `routes/console.php`.

### P5 — `listing_limit` no está siendo verificado al crear anuncios

**Problema:** El campo `listing_limit` en `plans` es 0, y no hay validación en `MariachiListingController::store()` que impida crear más anuncios de los que el plan permite.

---

## 12. Análisis del modelo de negocio

### Contexto del mercado

- **País:** Colombia
- **Moneda:** COP (pesos colombianos)
- **Competencia directa:** Directorios locales, grupos de WhatsApp/Facebook, recomendaciones boca a boca
- **Competencia de referencia de pricing:** Facebook Ads (~$1.500 COP por conversación vía WhatsApp click-to-chat)

### Propuesta de valor para el mariachi

El mariachi paga por dos cosas diferentes y hay que tenerlas claras:

| Cobro | Qué es | Analogía |
|---|---|---|
| **Activación de cuenta** ($19.800 one-time) | Derecho a existir en la plataforma. Como pagar la "membresía" | Netflix: pagas por tener acceso |
| **Pago de anuncio** (mensual) | Derecho a que su anuncio sea visible y aparezca en búsquedas | Facebook Ads: pagas por visibilidad |

Estos son dos cobros distintos con justificaciones distintas. Mezclarlos confunde al usuario.

### Análisis ROI para el mariachi

Datos reales del dueño:
- $300.000 en Facebook Ads → ~150 conversaciones → ~25 contratos
- Ganancia por serenata básica: ~$150.000 COP

**Con Facebook Ads:**
- Costo por conversación: $2.000 COP
- Costo por contrato: $12.000 COP
- ROI: $3.750.000 ganancia / $300.000 inversión = **12.5x**

**¿Qué puede ofrecer Mariachis.co que Facebook no ofrece?**

1. **SEO orgánico:** Un anuncio publicado en Mariachis.co puede rankear en Google por búsquedas como "mariachis en Bogotá" durante meses sin costo adicional.
2. **Audiencia calificada:** Quien visita Mariachis.co ya está buscando un mariachi. En Facebook, los anuncios interrumpen. En Mariachis.co, el cliente llega con intención.
3. **Perfil profesional permanente:** El anuncio incluye fotos, videos, reseñas, áreas de servicio y precio base. Mucho más completo que un anuncio de Facebook.
4. **Reseñas y reputación:** Los clientes dejan reseñas que aumentan la confianza del siguiente cliente.
5. **Recaptura de leads:** Cuando un anuncio vence, la plataforma muestra otros mariachis de la misma ciudad. El tráfico no se pierde.

### Modelos de cobro evaluados

#### Opción A: Por anuncio / suscripción mensual (modelo OLX)
- El mariachi paga una cuota mensual fija y su anuncio se muestra todo el mes
- Cuando no renueva, el anuncio se oculta (pero la URL sigue existiendo con redirect)
- **Ventajas:** Simple, predecible, fácil de vender, favorece el SEO
- **Desventajas:** El mariachi paga aunque no reciba solicitudes ese mes

#### Opción B: Por conversación/lead (modelo Facebook Ads)
- El mariachi paga cada vez que un cliente le escribe por WhatsApp o llena el formulario
- Precio sugerido: ~$2.000-3.000 COP por conversación
- **Ventajas:** El mariachi solo paga cuando hay resultados, muy justo
- **Desventajas:** Complejo de implementar (requiere tracking de conversaciones), difícil de auditar, el mariachi puede saltar el sistema dando su número directamente

#### Opción C: Modelo híbrido (recomendado)
- **Activación de cuenta:** $19.800 one-time → acceso a todos los servicios de la plataforma
- **Anuncio base gratuito** con visibilidad limitada (sin fotos destacadas, sin WhatsApp visible, sin prioridad)
- **Planes pagos** para aumentar visibilidad, capacidades y duración

**¿Por qué el híbrido?**

1. Baja la barrera de entrada: el mariachi puede probar la plataforma con un anuncio gratuito/básico
2. El plan de activación se justifica como "membresía" que da acceso a crear anuncios
3. Los planes mensuales se justifican como "publicidad" que aumenta visibilidad
4. Genera ingresos recurrentes (planes mensuales) + ingreso inicial (activación)
5. Crea un funnel: gratis → ve resultados → paga para crecer

### Conclusión del análisis

**Modelo recomendado: Suscripción mensual por anuncio (Opción A con elementos del C)**

Razones:
- El mariachi promedio en Colombia no está familiarizado con el modelo CPC/CPL (costo por clic/lead). El modelo mensual es más fácil de vender.
- La plataforma genera valor SEO que no existe en Facebook (tráfico orgánico acumulativo).
- El modelo mensual incentiva al mariachi a mantener su anuncio actualizado, lo que mejora la calidad de la plataforma.
- Es el mismo modelo de Booking.com, Airbnb, OLX — modelos conocidos y aceptados.
- Permite escalar: a medida que la plataforma crece y genera más tráfico, el valor del anuncio aumenta sin cambiar el precio.

---

## 13. Propuesta de pricing

### Activación de cuenta (one-time)

| Plan | Precio | Qué incluye |
|---|---|---|
| Activación estándar | **$19.800 COP** | Acceso al panel, crear perfil, crear anuncios |

Justificación: Es una cuota única de ingreso que filtra mariachis serios de los que solo quieren curiosear. Cubre el costo de moderación del primer perfil.

### Planes de anuncio (mensual / trimestral)

| Plan | Mensual | Trimestral | Semestral |
|---|---|---|---|
| **Básico** | $29.900 | $79.900 (~$3.400/día) | $149.900 |
| **Pro** | $59.900 | $159.900 | $299.900 |
| **Premium** | $99.900 | $269.900 | $499.900 |

### Tabla de beneficios por plan

| Beneficio | Básico | Pro | Premium |
|---|---|---|---|
| Anuncio visible en búsquedas | ✅ | ✅ | ✅ |
| Fotos en el anuncio | 5 | 15 | 30 |
| Videos en el anuncio | 1 | 3 | 6 |
| Botón WhatsApp visible | ❌ | ✅ | ✅ |
| Teléfono visible | ❌ | ✅ | ✅ |
| Posición en búsqueda | Normal | Alta | Máxima |
| Badge "Pro" / "Premium" | ❌ | ✅ Pro | ✅ Premium |
| Destacado en portada ciudad | ❌ | ❌ | ✅ |
| Destacado en home principal | ❌ | ❌ | ✅ |
| Estadísticas avanzadas | ❌ | ✅ | ✅ |
| Puede solicitar verificación | ❌ | ✅ | ✅ |

**Nota sobre WhatsApp:** Ocultar el WhatsApp en el plan básico es el incentivo más fuerte para hacer upgrade. El mariachi que no puede recibir mensajes directos por WhatsApp sentirá la necesidad de subir de plan.

### Verificación de perfil (opcional, one-time por período)

| Plan | Precio | Duración |
|---|---|---|
| Verificación anual | $49.900 COP | 12 meses |

Disponible solo para usuarios con plan Pro o Premium activo.

---

## 14. Roadmap de cambios

### Fase 1 — Flujo de activación (prioridad alta)

- [ ] Modificar middleware para permitir acceso al panel con `pending_activation`
- [ ] Crear banner de "cuenta inactiva" en el layout del partner
- [ ] Agregar campo `activation_deadline_at` a la tabla `users`
- [ ] Crear comando `PurgeUnactivatedAccounts` + schedulear (diario)
- [ ] Actualizar precio de activación a $19.800 en BD

### Fase 2 — Entitlements y planes (prioridad alta)

- [ ] Definir y cargar entitlements de cada plan (fotos, videos, WhatsApp, posición, etc.)
- [ ] Implementar validación en `MariachiListingController::uploadPhoto()` para respetar `max_photos`
- [ ] Ocultar botón de WhatsApp si el plan no incluye `show_whatsapp`
- [ ] Implementar lógica de prioridad en búsquedas según `priority_level`
- [ ] Mostrar badge Pro/Premium en tarjetas de anuncio

### Fase 3 — Mejoras de conversión (prioridad media)

- [ ] Página de comparación de planes con tabla de beneficios clara
- [ ] Email de recordatorio a mariachis con cuenta `pending_activation` (día 7 y día 13)
- [ ] Email de aviso de vencimiento de anuncio (7 días antes de `expires_at`)
- [ ] Descuento por pago trimestral/semestral (mostrar ahorro en COP)

### Fase 4 — Funcionalidades faltantes (prioridad media)

- [ ] Dashboard de métricas del mariachi: vistas, clics en WhatsApp, solicitudes recibidas
- [ ] Sistema de renovación automática (cobro recurrente con ePayco)
- [ ] Módulo de blog por ciudad para SEO local
- [ ] Integración completa con Google Merchant Center (feed de anuncios activos)

---

*Este documento debe actualizarse cada vez que se modifique el flujo de negocio, se agreguen planes o se cambie la pasarela de pagos.*
