fix(auditoria completa): bloqueos de Mi Dia, cobranza (saldos y fechas), captura (departamento y rol), contactos (privacidad), cotizador (QR) y validaciones de API
This commit is contained in:
@@ -1,10 +1,31 @@
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
import { z } from 'zod'
|
||||
import * as capturaService from '../services/captura-departamento.service.js'
|
||||
import { DEPARTAMENTOS } from '../config/campos-departamento.js'
|
||||
import { CAMPOS_POR_DEPARTAMENTO, DEPARTAMENTOS } from '../config/campos-departamento.js'
|
||||
import { AppError, BadRequestError } from '../utils/errors.js'
|
||||
import { esAdminOManager } from '../utils/roles.js'
|
||||
|
||||
// ── Validación de campos por departamento ────────────────────────────
|
||||
|
||||
/**
|
||||
* Cada campo debe pertenecer al departamento que se está guardando: si el
|
||||
* cliente manda un campo de otro departamento (p. ej. una captura de Obra
|
||||
* enviada como Ventas) se rechaza en vez de crear una fila basura.
|
||||
*/
|
||||
function validarCamposDelDepartamento(
|
||||
departamento: string,
|
||||
registros: { unidad: string; campo: string; valor: string | null }[],
|
||||
): void {
|
||||
const permitidos = new Set((CAMPOS_POR_DEPARTAMENTO[departamento] ?? []).map((c) => c.campo))
|
||||
const invalidos = registros.filter((r) => !permitidos.has(r.campo))
|
||||
if (invalidos.length > 0) {
|
||||
const lista = invalidos.slice(0, 3).map((r) => `${r.campo} (unidad ${r.unidad})`).join(', ')
|
||||
throw new BadRequestError(
|
||||
`El campo no pertenece al departamento ${departamento}: ${lista}${invalidos.length > 3 ? '…' : ''}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ── Middleware admin ─────────────────────────────────────────────────
|
||||
|
||||
function requireAdmin(req: Request, _res: Response, next: NextFunction): void {
|
||||
@@ -68,6 +89,7 @@ export async function guardarEndpoint(req: Request, res: Response): Promise<void
|
||||
if (!DEPARTAMENTOS.includes(body.departamento as typeof DEPARTAMENTOS[number])) {
|
||||
throw new BadRequestError(`Departamento inválido: ${body.departamento}`)
|
||||
}
|
||||
validarCamposDelDepartamento(body.departamento, [{ unidad: body.unidadCodigo, campo: body.campo, valor: body.valor ?? null }])
|
||||
|
||||
await capturaService.guardarCampo(
|
||||
body.desarrollo,
|
||||
@@ -102,6 +124,10 @@ export async function bulkEndpoint(req: Request, res: Response): Promise<void> {
|
||||
if (!DEPARTAMENTOS.includes(body.departamento as typeof DEPARTAMENTOS[number])) {
|
||||
throw new BadRequestError(`Departamento inválido: ${body.departamento}`)
|
||||
}
|
||||
validarCamposDelDepartamento(
|
||||
body.departamento,
|
||||
body.registros.map((r) => ({ unidad: r.unidad, campo: r.campo, valor: r.valor ?? null })),
|
||||
)
|
||||
|
||||
await capturaService.guardarBulk(
|
||||
body.desarrollo,
|
||||
|
||||
Reference in New Issue
Block a user