Validador de campañas
Overview
services/api/src/modules/campaigns/campaigns.validators.js define la validación local de payloads de campaña. Su objetivo es revisar los datos antes de que otras capas los usen, y devolver un resultado uniforme con valid y errors .
El archivo soporta validación completa y validación parcial. En modo parcial omite los campos obligatorios, pero sigue revisando todo campo que sí llegue en el payload. Ese comportamiento lo convierte en una barrera de entrada para creación y edición de campañas fileciteturn0file10turn0file11.
[!NOTE] Este módulo no lanza
ApiError. Devuelve un objeto estructurado para que la capa llamadora decida cómo responder.
How it works
flowchart TB
Input[Payload de campaña] --> Validator[validateCampaignPayload]
Validator --> Required[Campos obligatorios]
Validator --> Status[VALID_STATUSES]
Validator --> Objective[VALID_OBJECTIVES]
Validator --> Budget[Budget]
Validator --> Dates[Fechas]
Required --> Result[valid y errors]
Status --> Result
Objective --> Result
Budget --> Result
Dates --> Result
La función empieza con un arreglo vacío de errores. Si partial es false, exige name y listingId. Después valida cada campo presente: name, status, objective, budget.total, budget.spent, startDate y endDate. Al final devuelve { valid: errors.length === 0, errors } fileciteturn0file10turn0file11.
El flujo es acumulativo. La función no interrumpe en el primer fallo, sino que sigue revisando el resto de reglas. Eso permite devolver varios errores en una sola respuesta .
Key components
{
"title": "validateCampaignPayload",
"content": "Funci\u00f3n p\u00fablica exportada que valida el payload de una campa\u00f1a y devuelve un resultado con `valid` y `errors`. Admite validaci\u00f3n completa o parcial.",
"type": "function",
"filePath": "services/api/src/modules/campaigns/campaigns.validators.js",
"badges": [
"public"
]
}
VALID_STATUSES[badge:read-only] — Limitadata.statusadraft,active,paused,completedocancelledfileciteturn0file10turn0file11.VALID_OBJECTIVES[badge:read-only] — Limitadata.objectivealeads,visibility,callsomessagesfileciteturn0file10turn0file11.validateCampaignPayload[badge:public] — Revisa el payload y devuelve{ valid, errors }sin lanzar excepciones fileciteturn0file10turn0file11.
Data & fields
[
{
"name": "data",
"type": "object",
"required": true,
"description": "Payload de campaña que se quiere validar.",
"children": [
{
"name": "name",
"type": "string",
"description": "Nombre de la campaña. En modo completo es obligatorio. Si llega, debe ser un string no vacío."
},
{
"name": "listingId",
"type": "any",
"description": "Identificador del anuncio asociado. En modo completo es obligatorio por presencia."
},
{
"name": "status",
"type": "string",
"description": "Estado de la campaña. Debe pertenecer a `VALID_STATUSES` cuando se envía."
},
{
"name": "objective",
"type": "string",
"description": "Objetivo de la campaña. Debe pertenecer a `VALID_OBJECTIVES` cuando se envía."
},
{
"name": "budget",
"type": "object",
"description": "Objeto opcional de presupuesto.",
"children": [
{
"name": "total",
"type": "number",
"description": "Monto total del presupuesto. Debe ser un número mayor o igual a 0."
},
{
"name": "spent",
"type": "number",
"description": "Monto gastado. Debe ser un número mayor o igual a 0."
}
]
},
{
"name": "startDate",
"type": "date-compatible value",
"description": "Fecha de inicio. Debe convertirse en una fecha válida si se envía."
},
{
"name": "endDate",
"type": "date-compatible value",
"description": "Fecha de fin. Debe convertirse en una fecha válida si se envía."
}
]
},
{
"name": "options",
"type": "object",
"description": "Configuración opcional del validador.",
"children": [
{
"name": "partial",
"type": "boolean",
"description": "Omite la exigencia de `name` y `listingId` cuando es `true`. Por defecto es `false`."
}
]
},
{
"name": "result",
"type": "object",
"required": true,
"description": "Objeto devuelto por la función.",
"children": [
{
"name": "valid",
"type": "boolean",
"required": true,
"description": "Indica si el payload cumple todas las reglas."
},
{
"name": "errors",
"type": "string[]",
"required": true,
"description": "Lista de mensajes de validación acumulados."
}
]
}
]
Behaviors
validateCampaignPayload— Construye un arreglo de errores y devuelve el estado final convalidyerrors.VALID_STATUSES— Define el conjunto cerrado de estados aceptados para campañas fileciteturn0file10turn0file11.VALID_OBJECTIVES— Define el conjunto cerrado de objetivos aceptados para campañas fileciteturn0file10turn0file11.partial = false— Activa la validación completa y exigenameylistingIdfileciteturn0file10turn0file11.partial = true— Omite la exigencia de campos obligatorios, pero conserva la validación del resto de propiedades presentes fileciteturn0file10turn0file11.budget.totalybudget.spent— Solo aceptan números mayores o iguales a cero fileciteturn0file10turn0file11.startDateyendDate— Se validan por separado y cada una debe producir una fecha válida fileciteturn0file10turn0file11.
1. Recibir payload | La función recibe `data` y, opcionalmente, `{ partial }`.
2. Verificar obligatorios | Si `partial` es `false`, exige `name` y `listingId`.
3. Validar campos presentes | Revisa `name`, `status`, `objective`, `budget`, `startDate` y `endDate`.
4. Acumular errores | Cada incumplimiento añade un mensaje al arreglo `errors`.
5. Devolver resultado | Retorna `{ valid: errors.length === 0, errors }`.
Gotchas & edge cases
[!WARNING]
validateCampaignPayloaddesestructuradata.budgetcuandodata.budget !== undefined. Sibudgetllega comonull, la función falla antes de devolver{ valid, errors }.
[!IMPORTANT]
namese valida dos veces cuando viene en el payload. Primero como obligatorio en modo completo, y después como string no vacío.listingIdsolo se exige por presencia, no por formato, dentro de este archivo. fileciteturn0file10turn0file11
[!NOTE]
budgetsolo validatotalyspent. Cualquier otra propiedad interna del objeto se ignora en esta capa fileciteturn0file10turn0file11
[!NOTE]
startDateyendDatese evalúan de forma independiente. Cada campo puede fallar sin afectar al otro fileciteturn0file10turn0file11
Related
Este validador se conecta con el módulo de campañas del backend. services/api/src/modules/campaigns/campaigns.routes.js lo importa para crear y actualizar campañas, y services/api/src/models/Campaign.js define campos que coinciden con estas reglas, como status, objective, budget, startDate y endDate .
La relación funcional es directa: la ruta prepara el payload, llama a validateCampaignPayload, y solo sigue con la operación si no hay errores. Eso convierte a este archivo en una barrera previa a la persistencia de campañas fileciteturn0file10turn0file11.