feat: docs en apartados, enganche seleccionable y prefill de clientes

- Mis apartados (Mi día): botón Documentos con precarga del expediente —
  captura del cotizador y captura de pago apartado (obligatorios) más
  documentos generales; los archivos se guardan en el cliente ligado al
  apartado (se crea la ficha mínima si no existe). Endpoints
  GET/POST /apartados/:id/documentos (multipart, 10 MB, pdf/jpg/png)
- Cotizador: se oculta el editor de descuento (usan los % del Excel);
  enganche seleccionable con mínimo 2.5% del valor de la propiedad, solo
  en esquemas con crédito (bancario/Infonavit); mensualidades se
  recalculan con el enganche elegido y nunca quedan en negativo
- Cotizador: buscador de cliente en Monday (lead u oportunidad) que
  prellena nombre/contacto/desarrollo y vincula la cotización a la
  oportunidad al guardar
- Alta Afluencia: buscador que jala nombre, contacto, origen, desarrollo
  y modelo desde leads y oportunidades existentes
- buscarLeads devuelve desarrollo y modelo de interés
- Landing: el módulo Clientes vuelve a llamarse Cobranza
- Tests: 456 API + 94 cotizador + 14 mi-dia + 116 alta-clientes, verde
This commit is contained in:
2026-09-04 22:32:40 +00:00
parent 1963c06d93
commit cbd50e2066
19 changed files with 700 additions and 44 deletions

View File

@@ -85,3 +85,30 @@ export function cambiarEstadoApartado(itemId: string, estado: string): Promise<u
body: JSON.stringify({ estado }),
})
}
// ---------- Precarga de documentos del expediente (Mis apartados) ----------
export interface DocumentoApartado {
id: string
tipo: string // CAPTURA_COTIZADOR | CAPTURA_PAGO_APARTADO | OTRO | INE | ...
nombreArchivo: string
createdAt: string // ISO
}
/** GET /apartados/:itemId/documentos — documentos ya cargados del cliente ligado */
export function listarDocumentosApartado(itemId: string): Promise<DocumentoApartado[]> {
return fetchJson<DocumentoApartado[]>(`/apartados/${itemId}/documentos`)
}
/** POST /apartados/:itemId/documentos — multipart; el archivo se guarda en el cliente */
export async function subirDocumentoApartado(itemId: string, tipo: string, archivo: File): Promise<void> {
const form = new FormData()
form.append('tipo', tipo)
form.append('archivos', archivo)
const res = await fetch(`${API_URL}/apartados/${itemId}/documentos`, conAuth({ method: 'POST', body: form }))
manejar401(res)
if (!res.ok) {
const body = (await res.json().catch(() => null)) as { error?: string } | null
throw new Error(body?.error ?? `Error ${res.status}`)
}
}