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:
@@ -379,3 +379,68 @@ describe('mis cobranzas (toggle Mis planes / Todos)', () => {
|
||||
expect(r.planes.length).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('edición del plan y alcance sin planes asignados', () => {
|
||||
it('sinPlanesAsignados: solo cuando "míos" vino vacío desde el API', async () => {
|
||||
const { sinPlanesAsignados } = await import('./repository')
|
||||
expect(sinPlanesAsignados({ planes: [], origen: 'api', planesSoloLocales: false }, true)).toBe(true)
|
||||
// con resultados, con vista "todos" o en modo offline no aplica
|
||||
expect(sinPlanesAsignados({ planes: [planLocal()], origen: 'api', planesSoloLocales: false }, true)).toBe(false)
|
||||
expect(sinPlanesAsignados({ planes: [], origen: 'api', planesSoloLocales: false }, false)).toBe(false)
|
||||
expect(sinPlanesAsignados({ planes: [], origen: 'local', planesSoloLocales: false }, true)).toBe(false)
|
||||
})
|
||||
|
||||
it('puedeEditarMora: admin/manager/dirección sí; vendedor y roles de operación no', async () => {
|
||||
const { puedeEditarMora } = await import('./repository')
|
||||
expect(puedeEditarMora('admin')).toBe(true)
|
||||
expect(puedeEditarMora('manager')).toBe(true)
|
||||
expect(puedeEditarMora('direccion_general')).toBe(true)
|
||||
expect(puedeEditarMora('director_ventas')).toBe(true)
|
||||
expect(puedeEditarMora('coordinador')).toBe(true) // legacy de dirección
|
||||
expect(puedeEditarMora('vendedor')).toBe(false)
|
||||
expect(puedeEditarMora('administracion_venta')).toBe(false)
|
||||
expect(puedeEditarMora('escrituracion')).toBe(false)
|
||||
expect(puedeEditarMora(null)).toBe(false)
|
||||
expect(puedeEditarMora(undefined)).toBe(false)
|
||||
})
|
||||
|
||||
it('actualizarPlanAsync hace PATCH /planes/:id con la tasa de mora', async () => {
|
||||
const { actualizarPlanAsync } = await import('./repository')
|
||||
const fetchMock = fetchQue(async () => respuestaJson(planApi({ tasaMoraMensual: 2.5 })))
|
||||
vi.stubGlobal('fetch', fetchMock)
|
||||
|
||||
const r = await actualizarPlanAsync('api-1', { tasaMoraMensual: 2.5 })
|
||||
|
||||
expect(r.origen).toBe('api')
|
||||
expect(r.plan.tasaMoraMensual).toBe(2.5)
|
||||
expect(fetchMock).toHaveBeenCalledWith(
|
||||
`${API_URL}/planes/api-1`,
|
||||
expect.objectContaining({ method: 'PATCH', body: JSON.stringify({ tasaMoraMensual: 2.5 }) }),
|
||||
)
|
||||
})
|
||||
|
||||
it('actualizarPlanAsync propaga el 403 del API (rol sin permiso) sin tocar localStorage', async () => {
|
||||
const { actualizarPlanAsync } = await import('./repository')
|
||||
vi.stubGlobal(
|
||||
'fetch',
|
||||
fetchQue(async () => respuestaJson({ error: 'Solo admin, manager o dirección pueden modificar el plan' }, 403)),
|
||||
)
|
||||
|
||||
await expect(actualizarPlanAsync('api-1', { tasaMoraMensual: 2 }, crearStorageStub())).rejects.toBeInstanceOf(ErrorApi)
|
||||
})
|
||||
|
||||
it('actualizarPlanAsync cae a localStorage cuando falla la red', async () => {
|
||||
const { actualizarPlanAsync } = await import('./repository')
|
||||
vi.stubGlobal('fetch', fetchSinRed())
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
const storage = crearStorageStub()
|
||||
storage.setItem(CLAVE_STORAGE, JSON.stringify([planLocal()]))
|
||||
|
||||
const r = await actualizarPlanAsync('local-1', { tasaMoraMensual: 3 }, storage)
|
||||
|
||||
expect(r.origen).toBe('local')
|
||||
expect(r.plan.tasaMoraMensual).toBe(3)
|
||||
const guardado = JSON.parse(storage.getItem(CLAVE_STORAGE) ?? '[]') as PlanPago[]
|
||||
expect(guardado[0].tasaMoraMensual).toBe(3)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user