Lead model
Overview
services/api/src/models/Lead.js define el modelo Lead con Mongoose. Este modelo guarda leads en MongoDB, aplica validación básica sobre datos de contacto y conserva metadatos de origen y ciclo de vida.
También conecta cada lead con un Listing y un User mediante referencias de Mongoose. El esquema está pensado para consultas por propietario y por listado, gracias a sus índices explícitos.
[!NOTE] El modelo usa
timestamps: true, por lo que Mongoose añadecreatedAtyupdatedAtautomáticamente.
How it works
flowchart TB
Schema[Lead schema] --> Model[Lead model]
Schema --> Validation[Field validation and defaults]
Schema --> Refs[Listing and User references]
Schema --> Indexes[Index ownerId and listingId]
Model --> Collection[leads collection]
El archivo crea primero leadSchema con reglas de formato, valores por defecto y restricciones de enumeración. Después registra el modelo con mongoose.model('Lead', leadSchema) y lo exporta como Lead.
La colección usada es leads. El esquema también activa dos índices para acelerar búsquedas por ownerId y por listingId.
Key components
{
"title": "Lead",
"content": "Modelo de Mongoose que representa un lead persistido en la colecci\u00f3n leads. Define campos de contacto, referencias a Listing y User, estados de negocio y metadatos de origen.",
"type": "class",
"filePath": "services/api/src/models/Lead.js",
"badges": [
"public"
]
}
Data & fields
[
{
"name": "name",
"type": "String",
"required": true,
"description": "Nombre del lead. Se recorta con trim y admite hasta 120 caracteres."
},
{
"name": "email",
"type": "String",
"description": "Correo electrónico. Se recorta, se guarda en minúsculas y usa cadena vacía como valor por defecto."
},
{
"name": "phone",
"type": "String",
"description": "Teléfono de contacto. Se recorta y usa cadena vacía por defecto."
},
{
"name": "message",
"type": "String",
"description": "Mensaje asociado al lead. Se recorta, admite hasta 1000 caracteres y usa cadena vacía por defecto."
},
{
"name": "notes",
"type": "String",
"description": "Notas internas o adicionales. Se recorta, admite hasta 2000 caracteres y usa cadena vacía por defecto."
},
{
"name": "listingId",
"type": "ObjectId ref Listing",
"description": "Referencia al Listing relacionado. El valor por defecto es null."
},
{
"name": "listingTitle",
"type": "String",
"description": "Título del listing asociado. Se recorta y usa cadena vacía por defecto."
},
{
"name": "ownerId",
"type": "ObjectId ref User",
"required": true,
"description": "Referencia al usuario propietario del lead."
},
{
"name": "status",
"type": "String",
"description": "Estado operativo del lead. Valores permitidos: new, follow_up, closed, discarded. El valor por defecto es new."
},
{
"name": "source",
"type": "String",
"description": "Origen del lead. Valores permitidos: whatsapp, form, phone, email, manual, activity. El valor por defecto es manual."
},
{
"name": "createdDuringProtection",
"type": "Boolean",
"description": "Marca si el lead se creó durante el ciclo de cierre de cuenta de 60 días del titular del listing. El valor por defecto es false."
},
{
"name": "createdDuringAnonymization",
"type": "Boolean",
"description": "Marca si el lead se creó durante una fase de anonimización. El valor por defecto es false."
},
{
"name": "ownerStatusAtCreation",
"type": "String",
"description": "Estado del titular del listing en el momento de creación. Valores permitidos: active, pending_deletion, anonymized_pending_purge, purged, disabled. El valor por defecto es active."
},
{
"name": "deliveryStatus",
"type": "String",
"description": "Estado de entrega o notificación del lead. Valores permitidos: pending, notified, held, expired, purged. El valor por defecto es pending."
},
{
"name": "timestamps",
"type": "System metadata",
"description": "Mongoose añade createdAt y updatedAt automáticamente porque el esquema usa timestamps: true."
}
]
Field groups
Estos campos capturan el estado funcional del lead y el contexto en el que fue creado.
statuscontrola el ciclo comercial del lead.sourceclasifica el canal de origen.createdDuringProtectionycreatedDuringAnonymizationpreservan contexto histórico.ownerStatusAtCreationguarda el estado del titular al momento de creación.deliveryStatusdescribe la entrega o retención del lead.
Estos campos enlazan el lead con otras entidades del sistema.
listingIdreferencia aListing.ownerIdreferencia aUser.listingTitleguarda una copia textual del título del listing.
Behaviors
new mongoose.Schema(...)— Define validaciones, transformaciones y valores por defecto para cada campo del documento.leadSchema.index({ ownerId: 1, createdAt: -1 })— Crea un índice para consultas por propietario ordenadas por recencia.leadSchema.index({ listingId: 1 })— Crea un índice para búsquedas por listing.mongoose.model('Lead', leadSchema)— Registra el modeloLeady lo deja listo para persistencia y consultas.export const Lead— Exporta el modelo para que otros módulos lo importen y lo usen.
Gotchas & edge cases
[!WARNING] El comentario del esquema indica que, cuando
sourceesactivity,listingIddebe ser obligatorio e inmutable. Esa regla no vive en este archivo; se aplica enleads.routes.jspara la operaciónPATCH.
[!NOTE]
[!CAUTION]
ownerIdes obligatorio. Un documento sin esa referencia no cumple el esquema.
Related
Este modelo se relaciona directamente con Listing y User mediante referencias de Mongoose. También depende de la lógica de negocio que valida cambios sobre leads, según el comentario que apunta a leads.routes.js.
Listing— entidad referenciada porlistingId.User— entidad referenciada porownerId.leads.routes.js— contiene una regla de negocio mencionada en el comentario del esquema para el casosource = activity.
[!IMPORTANT] El esquema no define lógica de negocio ejecutable por sí mismo. Solo declara estructura, validación, valores por defecto e índices para la colección
leads.