feat(mi-dia): tabs Mis oportunidades/Mis apartados con fases y cotizador vinculado
- Resumen Mi día: misOportunidades.items (lista de trabajo con perfil y último cambio) y misApartados (Vendedor = yo, estados no finales) - Nuevos endpoints: POST /oportunidades/:id/etapa (Agendo Cita, Afluencia, Cotizador, Aparto, No Asistio, Abandono; con fecha de cita) y POST /apartados/:id/estado (pipeline Enkontrol: Pago Apartado → Firma Cliente (Venta) / Cancelacion Apartado); ambos mueven el item al grupo Monday correspondiente - Mi día: tabs Mis leads / Mis oportunidades / Mis apartados; botón Cotizar abre /quote con el cliente prellenado y la oportunidad ligada - Cotizador: prefill desde query params (cliente, teléfono, email, desarrollo, unidad) y envío de oportunidadId; al guardar, el API actualiza ESE item (Precio final, Tipo propuesta, etapa Cotizador) en vez de buscar por teléfono o crear duplicado - grupos-estado: 'Cancelacion Apartado' → Historico - Estados finales de apartado: agrega Firma Cliente (Venta) y Cancelacion Apartado - Tests: 455 API + 14 mi-dia + 88 cotizador, todo en verde
This commit is contained in:
53
api-gateway/src/controllers/apartados.controller.ts
Normal file
53
api-gateway/src/controllers/apartados.controller.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import type { Request, Response } from 'express'
|
||||
import { z } from 'zod'
|
||||
import { config } from '../config/index.js'
|
||||
import { mondayService, type MondayService } from '../services/monday.service.js'
|
||||
import { moverAGrupoSegunEstado } from '../services/grupos-estado.service.js'
|
||||
|
||||
/**
|
||||
* Pipeline Enkontrol del tablero Apartado: las fases que el vendedor puede
|
||||
* mover desde los botones de "Mis apartados" en Mi día. Son los labels REALES
|
||||
* de la columna status 'Estado' del board (verificados en Monday) — el
|
||||
* frontend los manda tal cual.
|
||||
*/
|
||||
export const FASES_APARTADO_PERMITIDAS = [
|
||||
'Pago Apartado',
|
||||
'Alta Enkontrol',
|
||||
'Entrego Documentacion',
|
||||
'Cita Clientes',
|
||||
'Contrato Enkontrol',
|
||||
'Firma Cliente (Venta)',
|
||||
'Cancelacion Apartado',
|
||||
] as const
|
||||
|
||||
const cambiarEstadoSchema = z.object({
|
||||
estado: z.enum(FASES_APARTADO_PERMITIDAS),
|
||||
})
|
||||
|
||||
type MondayApartados = Pick<
|
||||
MondayService,
|
||||
'cambiarValorColumna' | 'columnaIdPorTitulo' | 'getItemConGrupo' | 'moverItemAGrupo'
|
||||
>
|
||||
|
||||
/**
|
||||
* Cambia la fase del apartado (columna 'Estado') y mueve el item al grupo que
|
||||
* corresponde (idempotente; el webhook de change haría lo mismo, pero así la
|
||||
* UI responde al instante).
|
||||
*/
|
||||
export async function cambiarEstadoApartado(
|
||||
monday: MondayApartados,
|
||||
itemId: string,
|
||||
estado: (typeof FASES_APARTADO_PERMITIDAS)[number],
|
||||
): Promise<void> {
|
||||
const boardApartado = config.monday.boards.apartado
|
||||
await monday.cambiarValorColumna(boardApartado, itemId, 'Estado', estado)
|
||||
await moverAGrupoSegunEstado(monday, boardApartado, itemId)
|
||||
}
|
||||
|
||||
/** POST /api/apartados/:itemId/estado { estado } */
|
||||
export async function cambiarEstadoApartadoEndpoint(req: Request, res: Response): Promise<void> {
|
||||
const body = cambiarEstadoSchema.parse(req.body)
|
||||
const itemId = String(req.params['itemId'])
|
||||
await cambiarEstadoApartado(mondayService, itemId, body.estado)
|
||||
res.json({ itemId, estado: body.estado })
|
||||
}
|
||||
Reference in New Issue
Block a user