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:
@@ -20,6 +20,7 @@ const respuesta = (data: unknown, status = 200) =>
|
||||
const almacenamiento = new Map<string, string>()
|
||||
beforeEach(() => {
|
||||
almacenamiento.clear()
|
||||
window.history.replaceState({}, '', '/')
|
||||
vi.stubGlobal('localStorage', {
|
||||
getItem: (k: string) => almacenamiento.get(k) ?? null,
|
||||
setItem: (k: string, v: string) => void almacenamiento.set(k, v),
|
||||
@@ -88,4 +89,58 @@ describe('CotizadorPage — barra sticky y guardado local', () => {
|
||||
})
|
||||
expect(screen.getByText(/cotización guardada localmente con folio CTE-LOCAL-/)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('no deja cotizar una unidad que ya no está disponible: avisa y bloquea las acciones', async () => {
|
||||
const vendida = { ...unidad, codigo: 'U-900', status: 'VENDIDO' as const }
|
||||
const cotizacionVendida = {
|
||||
id: 'cot-vendida',
|
||||
folio: 'COT-VENDID',
|
||||
unidadCodigo: vendida.codigo,
|
||||
desarrollo: 'DIAGONAL',
|
||||
clienteNombre: 'Cliente Antiguo',
|
||||
clienteTelefono: null,
|
||||
clienteEmail: null,
|
||||
tipoPropuesta: 'BANCARIO',
|
||||
acabados: false,
|
||||
apartado: 20000,
|
||||
descuento: 0,
|
||||
precioLista: vendida.precioConAcabados,
|
||||
precioFinal: 0,
|
||||
enganche: 0,
|
||||
numMensualidades: 12,
|
||||
mensualidad: 1000,
|
||||
pagoFinal: 0,
|
||||
createdAt: '2026-09-01T00:00:00.000Z',
|
||||
}
|
||||
const fetchMock = vi.fn((input: RequestInfo | URL) => {
|
||||
const url = String(input)
|
||||
if (url.includes('/unidades')) return Promise.resolve(respuesta([unidad, vendida]))
|
||||
if (url.includes('/cotizaciones/mias')) return Promise.resolve(respuesta([cotizacionVendida]))
|
||||
return Promise.reject(new TypeError(`fetch inesperado: ${url}`))
|
||||
})
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
// Prellenado desde Mi día con una unidad que ya se vendió
|
||||
window.history.replaceState({}, '', `/?unidad=${vendida.codigo}`)
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<CotizadorPage />
|
||||
</MemoryRouter>,
|
||||
)
|
||||
|
||||
// El prellenado NO la preselecciona y lo dice
|
||||
expect(await screen.findByText(/ya no está disponible \(estatus: VENDIDO\)/)).toBeTruthy()
|
||||
|
||||
// Retomar la cotización vieja de esa unidad: se restaura, pero avisa y
|
||||
// deja Guardar/Compartir/Generar PDF bloqueados
|
||||
fireEvent.click(await screen.findByRole('button', { name: /Ver historial/ }))
|
||||
fireEvent.click(await screen.findByRole('button', { name: 'Retomar' }))
|
||||
|
||||
const alerta = await screen.findByRole('alert')
|
||||
expect(alerta.textContent).toContain(`La unidad ${vendida.codigo} no está disponible`)
|
||||
expect(screen.getByText(/ya no está disponible \(estatus: VENDIDO\): no se puede cotizar de nuevo/)).toBeTruthy()
|
||||
for (const nombre of ['Generar PDF', 'Guardar', 'Compartir']) {
|
||||
expect((screen.getByRole('button', { name: nombre }) as HTMLButtonElement).disabled).toBe(true)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user