feat(pendientes): cotizador (mensualidades, bloqueo de unidad, totales, numMensualidades), cobranza (recibos, atrasos, mora configurable, recordatorios), soporte (adjuntos, filtros, estados), clientes maestro (catalogos reales), contactos (ficha y duplicados) y permisos de captura por rol

This commit is contained in:
2026-09-21 08:34:53 +00:00
parent b5a20aed4e
commit 2fc80e7f9e
66 changed files with 3792 additions and 436 deletions

View File

@@ -1,4 +1,5 @@
export const DEPARTAMENTOS = ['OBRA', 'VENTAS', 'ESCRITURACION', 'FINANZAS', 'POSTVENTA'] as const
export type Departamento = (typeof DEPARTAMENTOS)[number]
export const CAMPOS_POR_DEPARTAMENTO: Record<string, { campo: string; tipo: string; label: string; options?: string[]; conFecha?: string }[]> = {
OBRA: [
@@ -59,3 +60,44 @@ export const CAMPOS_POR_DEPARTAMENTO: Record<string, { campo: string; tipo: stri
}
export const DESARROLLOS = ['SENDA', 'ATELIER', 'ESTANZA', 'DIAGONAL', 'SOLANA', 'SOLE', 'MUTUO'] as const
// ── Permisos de captura por rol ───────────────────────────────────────
/**
* Departamentos que cada rol puede ver y capturar. Fuente de verdad del
* ecosistema: el front espeja esta misma matriz en services/captura.ts para
* ocultar pestañas, pero quien la hace cumplir es el API.
*
* Dirección y administración ven todos (incluye los roles legacy de la matriz
* de módulos: 'director', 'coordinador'); cada rol operativo sólo el suyo.
*/
export const DEPARTAMENTOS_POR_ROL: Record<string, readonly Departamento[]> = {
admin: DEPARTAMENTOS,
manager: DEPARTAMENTOS,
direccion_general: DEPARTAMENTOS,
director_ventas: DEPARTAMENTOS,
administracion_venta: DEPARTAMENTOS,
director: DEPARTAMENTOS,
coordinador: DEPARTAMENTOS,
vendedor: ['VENTAS'],
escrituracion: ['ESCRITURACION'],
cobranza: ['FINANZAS'],
postventa: ['POSTVENTA'],
obra: ['OBRA'],
}
/**
* Departamentos del rol. Sin token (AUTH_ENABLED=false, modo local) no hay
* restricción; un rol desconocido cae a vendedor, igual que modulosDeRol
* (fallback seguro: es el conjunto más chico).
*/
export function departamentosDeRol(rol: string | undefined): readonly Departamento[] {
const clave = (rol ?? '').trim().toLowerCase()
if (clave === '') return DEPARTAMENTOS
return DEPARTAMENTOS_POR_ROL[clave] ?? DEPARTAMENTOS_POR_ROL['vendedor']!
}
/** ¿El rol puede ver/capturar ese departamento? */
export function rolPuedeDepartamento(rol: string | undefined, departamento: string): boolean {
return (departamentosDeRol(rol) as readonly string[]).includes(departamento)
}