Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Giofelix/Proyecto-automatizacion-Empresa/llms.txt

Use this file to discover all available pages before exploring further.

El módulo Reteica del sistema municipal de impuestos gestiona la retención de industria y comercio a través de cuatro pantallas principales relacionadas jerárquicamente: el catálogo de Terceros (personas naturales y jurídicas), el registro de Contribuyentes (terceros inscritos ante el municipio), el sub-módulo de Establecimientos (sedes comerciales de cada contribuyente) y el flujo de Presentar Declaración (declaración periódica de retención). Cada pantalla tiene su propio Page Object que extiende los componentes comunes con locators y métodos específicos de su formulario.

Terceros

Catálogo de terceros con pestañas Básicos y Adicionales.

Contribuyentes

Registro de contribuyentes y navegación al menú de procesos.

Establecimientos

Sedes comerciales de un contribuyente con formulario de dos pestañas.

PresentarDeclaracion

Wizard de 4 pasos para declaraciones periódicas de Reteica.

Terceros

Archivo: pages/modulos/reteica/archivos/terceros.page.js La página de Terceros organiza el formulario de datos del tercero en dos pestañas de Angular Material: Básicos (información fiscal y de contacto) y Adicionales (ubicación geográfica y datos complementarios). Los combos de régimen, naturaleza, país, departamento y ciudad utilizan componentes app-combo con botones de tipo play_arrow que no tienen nombre ARIA, por lo que se localizan mediante el texto de contenido del icono.

Constructor — locators principales

Pestaña Básicos

PropiedadLocatorDescripción
tabBasicospage.getByRole('tab', { name: 'Basicos' })Pestaña Básicos del formulario
inputNitpage.getByRole('textbox', { name: 'Nit' })NIT del tercero (Tab dispara cálculo del dígito de verificación)
inputRazonSocialpage.getByRole('textbox', { name: 'Primer nombre / Razón social' })Razón social o primer nombre
inputDigitoVerificacionpage.getByRole('spinbutton', { name: 'Dígito de verificación' })Campo de solo lectura (auto-calculado)
comboTipoRegimenpage.getByRole('combobox', { name: 'Tipo regimen' })Selector de tipo de régimen
btnTipoRegimenpage.locator('mat-form-field').filter({ hasText: 'Tipo regimen' }).getByRole('button')Botón play_arrow del combo Tipo regimen
comboNaturalezapage.getByRole('combobox', { name: 'Naturaleza' })Selector de naturaleza (campo requerido)
btnNaturalezapage.locator('mat-form-field').filter({ hasText: 'Naturaleza' }).getByRole('button')Botón play_arrow del combo Naturaleza
inputDireccionpage.getByRole('textbox', { name: 'Dirección' })Dirección del tercero
inputTelefonospage.getByRole('textbox', { name: 'Teléfonos' })Teléfonos de contacto
comboTipoDocumentopage.getByRole('combobox', { name: 'Tipo de documento' })Tipo de documento de identidad
btnTipoDocumentopage.locator('mat-form-field').filter({ hasText: 'Tipo de documento' }).getByRole('button')Botón del combo Tipo de documento

Pestaña Adicionales

PropiedadLocatorDescripción
tabAdicionalespage.getByRole('tab', { name: 'Adicionales' })Pestaña Adicionales del formulario
comboPaispage.getByRole('combobox', { name: 'Pais' })Combo de país
btnPaispage.locator('#ID_PAIS').getByRole('button').filter({ hasText: 'play_arrow' })Botón del app-combo País (localizado por ID propio del componente)
comboDepartamentopage.getByRole('combobox', { name: 'Departamento' })Combo de departamento
btnDepartamentopage.locator('#ID_DEPARTAMENTO').getByRole('button').filter({ hasText: 'play_arrow' })Botón del app-combo Departamento
comboCiudadpage.getByRole('combobox', { name: 'Ciudad' })Combo de ciudad (campo requerido)
btnCiudadpage.locator('mat-form-field').filter({ hasText: 'Ciudad' }).getByRole('button')Botón del combo Ciudad
inputEmailpage.getByRole('textbox', { name: 'Direccion E-mail' })Dirección de correo electrónico

Métodos

completarDatosBasicos(datos)

Hace clic en la pestaña Básicos y rellena los campos del formulario con los valores proporcionados.
datos
object
required
Objeto con los campos de la pestaña Básicos.

completarDatosAdicionales(datos)

Hace clic en la pestaña Adicionales y rellena los combos de ubicación y el email.
datos
object
required
Objeto con los campos de la pestaña Adicionales.

Ejemplo

import { Terceros } from './pages/modulos/reteica/archivos/terceros.page.js';

const terceros = new Terceros(page);

await terceros.completarDatosBasicos({
  nit: '900123456',
  tipoDocumento: 'NIT',
  razonSocial: 'EMPRESA DEMO SAS',
  tipoRegimen: 'Menores Ingresos',
  direccion: 'CL 18 25 50',
  telefonos: '6027234567',
  naturaleza: 'PERSONA JURIDICA',
});

await terceros.completarDatosAdicionales({
  pais: 'Colombia',
  departamento: 'BOYACA',
  ciudad: 'BOYACA',
  email: 'test@example.com',
});
El dígito de verificación (inputDigitoVerificacion) es calculado automáticamente por el sistema en el backend al recibir el NIT. No debes escribirlo manualmente; el press('Tab') en completarDatosBasicos dispara el blur que inicia ese cálculo.

Contribuyentes

Archivo: pages/modulos/reteica/archivos/contribuyentes/contribuyentes.page.js La página de Contribuyentes gestiona el catálogo de contribuyentes del municipio. El flujo de creación implica un diálogo Nuevo Registro con un selector de terceros que se abre como mat-bottom-sheet. La vista de detalle expone un menú more_vert que da acceso a procesos secundarios como declaraciones, pagos parciales y estados de cuenta.

Constructor — locators principales

Diálogo Nuevo Registro

PropiedadLocatorDescripción
dialogoNuevoRegistropage.getByRole('dialog', { name: 'Nuevo Registro' })Contenedor del diálogo de creación
selectorNombredialogoNuevoRegistro.getByRole('listbox', { name: 'Nombre' })Abre el selector de terceros (mat-bottom-sheet)
inputMatriculadialogoNuevoRegistro.getByRole('textbox', { name: 'Matrícula', exact: true })Número de matrícula del contribuyente
inputFechaMatriculadialogoNuevoRegistro.getByRole('textbox', { name: 'Fecha matrícula' })Fecha de matrícula del establecimiento

Selector de Terceros (mat-bottom-sheet)

PropiedadLocatorDescripción
dialogoSelectorTercerospage.getByRole('dialog').filter({ has: page.locator('mat-tab-group') })Diálogo con pestañas DATOS / FILTROS
tabDatosTercerospage.getByRole('tab', { name: /datos/i })Pestaña de resultados de la búsqueda
tabFiltrosTercerospage.getByRole('tab', { name: /filtros/i })Pestaña de criterios de filtro
inputFiltroNitpage.locator('mat-tab-group').getByRole('textbox', { name: /nit/i })Campo de filtro por NIT
btnAplicarFiltropage.getByRole('button', { name: 'Aplicar' })Ejecuta la búsqueda con los filtros activos
gridTercerosCeldaNit(nit)page.locator('mat-bottom-sheet-container mat-row').filter({ has: page.locator('mat-cell.cdk-column-NIT', { hasText: nit }) }).first()Fila del tercero en el mat-bottom-sheet (NO en la tabla principal)

Página de Detalle

PropiedadLocatorDescripción
btnMenuProcesospage.getByRole('button').filter({ hasText: 'more_vert' })Botón de menú de procesos adicionales
menuProcesospage.getByRole('menu')Panel del menú desplegado
inputNitpage.getByRole('textbox', { name: 'Nit del propietario' })NIT del tercero vinculado (solo lectura en detalle)
inputNombrepage.getByRole('textbox', { name: 'Nombre' })Nombre del contribuyente
inputEstadopage.getByRole('textbox', { name: 'Estado' })Estado del contribuyente (activo/inactivo)

Métodos

irAProcesoDesdeMenu(nombreOpcion)

Abre el menú more_vert y hace clic en la opción indicada, esperando networkidle tras la navegación.
nombreOpcion
string
required
Nombre exacto del ítem de menú (valor de name en getByRole('menuitem')). Opciones disponibles definidas en el constructor: 'Declaraciones', 'Actualizar otros impuestos', 'Emplazamiento por no declarar', 'Pagos parciales', 'Edicion de abonos', 'Terceros asociados', 'Documentos RIT', 'Activar', 'Bitacora estado', 'Facturas', 'Estado de cuenta', 'Generar RIT', 'Generar RIC', 'Histórico de declaraciones'.
await contribuyentes.irAProcesoDesdeMenu('Declaraciones');

verificarContribuyenteEnTabla(nit)

nit
string
required
NIT exacto del contribuyente a verificar en la tabla.
Verifica que el contribuyente identificado por nit aparece en la tabla principal. Si la fila no está visible en la página actual, abre automáticamente el diálogo de filtro “Búsqueda por:”, filtra por NIT, cierra el diálogo y luego afirma la visibilidad de la celda con expect(...).toBeVisible().

seleccionarTerceroPorNit(nit)

nit
string
required
NIT del tercero a seleccionar en el picker.
Navegación interna del selector de Terceros que abre como mat-bottom-sheet:
  1. Hace clic en la pestaña Filtros y escribe el NIT en inputFiltroNit.
  2. Hace clic en Aplicar y cambia a la pestaña Datos.
  3. Espera que la fila del tercero sea visible en mat-bottom-sheet-container y la selecciona con force: true (necesario por la intercepción de pointer events de Angular Material).
  4. Espera que mat-bottom-sheet-container sea detached del DOM antes de retornar.

completarNuevoRegistro(datos)

datos
object
required

Ejemplo

import { Contribuyentes } from './pages/modulos/reteica/archivos/contribuyentes/contribuyentes.page.js';
import { AccionesCrud } from './pages/common/acciones-crud.js';

const contribuyentes = new Contribuyentes(page);
const crud = new AccionesCrud(page);

// Crear nuevo contribuyente
await crud.agregar();
await contribuyentes.completarNuevoRegistro({
  nitTercero: '900123456',
  matricula: 'MAT-001',
  fecha: '01/01/2024',
});
await contribuyentes.aceptarNuevoRegistro();

// Verificar que aparece en la tabla
await contribuyentes.verificarContribuyenteEnTabla('900123456');

// Abrir el detalle y navegar al proceso de declaraciones
await contribuyentes.irAProcesoDesdeMenu('Declaraciones');
El mat-bottom-sheet del selector de Terceros puede dejar un cdk-global-overlay-wrapper bloqueando los pointer events tras cerrarse. Los métodos seleccionarTerceroPorNit y aceptarNuevoRegistro usan force: true de forma deliberada para bypassear ese bloqueo transitorio.

Establecimientos

Archivo: pages/modulos/reteica/archivos/contribuyentes/menu-procesos-contribuyentes/establecimientos.page.js La página de Establecimientos gestiona las sedes comerciales asociadas a un contribuyente. El formulario de creación y edición se divide en dos pestañas de Angular Material — Básica (datos obligatorios de contacto y ubicación) y Adicional (datos complementarios opcionales). La navegación de vuelta a la lista se realiza a través del breadcrumb, ya que el formulario no expone un botón Cancelar explícito.

Constructor — locators principales

Tabla principal

PropiedadLocatorDescripción
tablaGridpage.getByRole('grid')Grid principal de la lista de establecimientos
columnaCodigopage.getByRole('columnheader', { name: 'Código' })Encabezado de columna Código
columnaNombrepage.getByRole('columnheader', { name: 'Nombre' })Encabezado de columna Nombre
btnMenuListapage.getByRole('button').filter({ hasText: 'more_vert' })Menú contextual de la lista (more_vert)
menuItemRegistrarActividadespage.getByRole('menuitem', { name: 'Registrar actividades' })Ítem de menú para registrar actividades

Formulario — pestaña Básica

PropiedadLocatorDescripción
tabBasicapage.getByRole('tab', { name: 'Básica' })Pestaña Básica del formulario
inputNombrepage.getByRole('textbox', { name: 'Nombre' })Nombre del establecimiento (obligatorio)
inputTelefonopage.getByRole('spinbutton', { name: 'Teléfono' })Teléfono (obligatorio, tipo número)
btnPaispage.locator('mat-form-field').filter({ hasText: 'País' }).getByRole('button')Botón play_arrow del combo País (obligatorio)
btnDepartamentopage.locator('mat-form-field').filter({ hasText: 'Departamento' }).getByRole('button')Botón del combo Departamento (se habilita tras País)
btnCiudadpage.locator('mat-form-field').filter({ hasText: 'Ciudad' }).getByRole('button')Botón del combo Ciudad (se habilita tras Departamento)
btnBarriopage.locator('mat-form-field').filter({ hasText: 'Barrio' }).getByRole('button')Botón del combo Barrio (obligatorio)
inputDireccionpage.getByRole('textbox', { name: 'Dirección' })Dirección del establecimiento (obligatorio)
inputCorreoElectronicopage.getByRole('textbox', { name: 'Correo electronico' })Correo electrónico (obligatorio)
inputInicioActividadpage.getByRole('textbox', { name: 'Inicio actividad' })Fecha de inicio de actividad (obligatorio)
btnBreadcrumbEstablecimientospage.getByRole('button', { name: 'Establecimientos' })Botón de breadcrumb para volver a la lista

Formulario — pestaña Adicional

PropiedadLocatorDescripción
tabAdicionalpage.getByRole('tab', { name: 'Adicional' })Pestaña Adicional del formulario
inputCodigoCatastralpage.getByRole('textbox', { name: 'Código catastral' })Código catastral (opcional)
inputPaginaWebpage.getByRole('textbox', { name: 'Página web' })Página web (opcional)
inputCodigoPostalpage.getByRole('textbox', { name: 'Código postal' })Código postal (opcional)
inputCodigoAdicionalpage.getByRole('tabpanel', { name: 'Adicional' }).getByPlaceholder('Código', { exact: true })Campo Código adicional (opcional)

Métodos

completarTabBasica(datos)

Rellena todos los campos de la pestaña Básica. Los combos geográficos encadenados (País → Departamento → Ciudad → Barrio) se completan con seleccionarOpcionPlayArrow().
datos
object
required

completarTabAdicional(datos)

Cambia a la pestaña Adicional y rellena los campos opcionales definidos en el objeto.
datos
object
required
Objeto con claves opcionales: codigoCatastral, paginaWeb, codigoPostal, codigoAdicional. Todos de tipo string.

verificarEstablecimientoEnTabla(codigo)

codigo
string
required
Código exacto del establecimiento a verificar.
Afirma con expect(...).toBeVisible({ timeout: 15000 }) que existe una gridcell con el código exacto en la tabla principal.

abrirEstablecimiento(nombre)

nombre
string
required
Nombre exacto del establecimiento tal como aparece en la tabla.
Hace clic en la celda del nombre y espera networkidle para la carga del formulario de detalle.

cancelar()

Navega de vuelta a la lista usando el botón del breadcrumb (btnBreadcrumbEstablecimientos) y espera a que la grilla o el mensaje “No existe información” sean visibles.

irARegistrarActividades()

Abre el menú more_vert de la lista y hace clic en Registrar actividades, esperando networkidle.

completarFiltros(filtros)

Rellena el diálogo de filtro “Búsqueda por:” con los criterios proporcionados y confirma con el botón Aceptar.
filtros
object
required
Objeto con claves opcionales: codigo, nombre, telefono, direccion, estado, matricula, fechaMatricula, inicioActividad. Todos de tipo string.

Ejemplo

import { Establecimientos } from './pages/modulos/reteica/archivos/contribuyentes/menu-procesos-contribuyentes/establecimientos.page.js';
import { AccionesCrud } from './pages/common/acciones-crud.js';

const establecimientos = new Establecimientos(page);
const crud = new AccionesCrud(page);

// Crear un nuevo establecimiento
await crud.agregar();
await establecimientos.completarTabBasica({
  nombre: 'SEDE PRINCIPAL',
  telefono: '6027234567',
  pais: 'Colombia',
  departamento: 'BOYACA',
  ciudad: 'BOYACA',
  barrio: 'CENTRO',
  direccion: 'CL 18 25 50',
  correoElectronico: 'sede@empresa.com',
  inicioActividad: '01/01/2020',
});
await crud.guardar();
await crud.aceptar();

// Verificar que aparece en la tabla
await establecimientos.verificarEstablecimientoEnTabla('001');
El campo Código del establecimiento es autogenerado por el sistema y está deshabilitado en el formulario. No debe llenarse manualmente. El campo Consecutivo matrícula también es autogenerado.

PresentarDeclaracion

Archivo: pages/modulos/reteica/archivos/contribuyentes/menu-procesos-contribuyentes/presentar-declaracion.page.js PresentarDeclaracion encapsula el wizard de cuatro pestañas para presentar una declaración periódica de Reteica. Cada pestaña corresponde a un paso del proceso: selección del período gravable, asignación de establecimientos, ingreso de valores de liquidación y firma electrónica mediante el diálogo de Terceros Asociados.

Wizard — estructura de pestañas

#Nombre de pestañaLocatorAcción de avance
1Año gravablepage.getByRole('tab', { name: 'Año gravable' })btnSiguienteAnio (mat-raised-button)
2Establecimientospage.getByRole('tab', { name: 'Establecimientos' })btnSiguienteEstablecimientos
3Liquidación de conceptospage.getByRole('tab', { name: 'Liquidación de conceptos' })btnSiguienteLiquidacion
4Declaraciónpage.getByRole('tab', { name: 'Declaración' })— (finaliza con el diálogo de terceros)

Constructor — locators principales

Sección 1 — Año gravable

PropiedadLocator
btnAniopage.locator('mat-form-field').filter({ hasText: 'Seleccione el año a declarar' }).getByRole('button')
btnPeriodopage.locator('mat-form-field').filter({ hasText: 'Período' }).getByRole('button')
btnTipoDeclaracionpage.locator('mat-form-field').filter({ hasText: 'Tipo de declaración' }).getByRole('button')
inputFechaPresentacionpage.getByRole('textbox', { name: 'Fecha de presentación' })
checkEntidadPublicapage.getByRole('checkbox', { name: 'Entidad publica u otros.' })
dialogoConfirmacionpage.getByRole('dialog', { name: 'Confirmación' })

Sección 3 — Liquidación de conceptos

Los campos de liquidación se dividen en dos grupos dentro del mismo tabpanel:
  • Solo lectura (input[readonly][placeholder="..."]): valores calculados por el sistema. Locators con prefijo inputSist*.
  • Editables (input:not([readonly])[placeholder="..."]): valores ingresados por el usuario. Locators con prefijo inputLiq*.
Los campos disponibles en ambos grupos son: COMPRAS, SERVICIOS, INDUSTRIA, FINANCIERA, AUTORETENCION VENTAS, AUTORETENCION SERVICIOS, AUTORETENCION OTROS CONCEPTOS, TOTAL RETENCIONES, INTERES DE MORA, EXTEMPORANEIDAD, TOTAL SALDO A CARGO, VALOR A PAGAR, MAS OTRAS SANCIONES, SANCIÓN POR CORRECCIÓN, TOTAL SANCION, TOTAL A PAGAR.
PropiedadLocator
dialogoTercerosAsociadospage.getByRole('dialog').filter({ has: page.getByRole('heading', { name: 'Terceros asociados' }) })
btnDeclTipoDeclarantedialogoTercerosAsociados.locator('mat-form-field').filter({ hasText: 'Tipo declarante' }).getByRole('button')
btnDeclTipoDocumentodialogoTercerosAsociados.locator('mat-form-field').filter({ hasText: 'Tipo de documento' }).getByRole('button').nth(0)
inputDeclNumeroDocumentodialogoTercerosAsociados.getByRole('textbox', { name: 'Número de documento' }).nth(0)
inputDeclNombresdialogoTercerosAsociados.getByRole('textbox', { name: 'Nombres' }).nth(0)
btnGuardarDialogodialogoTercerosAsociados.getByRole('button', { name: 'Guardar' })
Dentro del diálogo de Terceros Asociados existen dos instancias de los campos Tipo de documento, Número de documento y Nombres: nth(0) corresponde al declarante y nth(1) al contador o revisor fiscal.

Métodos

completarSeccion1(datos)

Selecciona año, período y tipo de declaración, y opcionalmente rellena la fecha de presentación.
datos
object
required

completarSeccion3(datos)

Rellena los campos editables de la sección de Liquidación de conceptos. Todos los campos son opcionales; sólo se invoca fill() para los que estén definidos en el objeto.
datos
object
required
Objeto con claves: compras, servicios, industria, financiera, autoRetencionVentas, autoRetencionServicios, autoRetencionOtros, interesMora, extemporaneidad, masOtrasSanciones, sancionCorreccion. Todos de tipo string (valor monetario como texto).

actualizarLiquidacion()

Hace clic en el botón Actualizar de la sección 3 y espera networkidle (30 s). Esto recalcula los totales (TOTAL RETENCIONES, TOTAL SALDO A CARGO, TOTAL A PAGAR, etc.) en el panel de Liquidación del sistema.

avanzarDesdeEstablecimientos()

Hace clic en btnSiguienteEstablecimientos y espera networkidle. Avanza del paso 2 al paso 3.

avanzarDesdeLiquidacion()

Hace clic en btnSiguienteLiquidacion y espera networkidle. Avanza del paso 3 al paso 4 y abre automáticamente el diálogo de Terceros Asociados.

completarDatosDeclarante(datos)

Rellena la sub-sección Datos declarante del diálogo Terceros Asociados.
datos
object
required

guardarTercerosAsociados()

Hace clic en el botón Guardar del diálogo de Terceros Asociados y espera networkidle.

verificarTabActiva(nombreTab)

nombreTab
string
required
Nombre de la pestaña que debe estar activa (valor del atributo aria-selected="true").
Usa expect(tab).toHaveAttribute('aria-selected', 'true') para asegurar que el wizard se encuentra en el paso correcto.

verificarDialogoTercerosVisible()

Afirma con expect(dialogoTercerosAsociados).toBeVisible({ timeout: 15000 }) que el diálogo de Terceros Asociados está visible. Se usa como precondición antes de completarDatosDeclarante().

Ejemplo de flujo completo

import { PresentarDeclaracion } from './pages/modulos/reteica/archivos/contribuyentes/menu-procesos-contribuyentes/presentar-declaracion.page.js';

const declaracion = new PresentarDeclaracion(page);

// Paso 1: Año gravable
await declaracion.completarSeccion1({
  anio: '2024',
  periodo: 'ENERO',
  tipoDeclaracion: 'MENSUAL',
  fechaPresentacion: '15/02/2024',
});
// Manejar diálogo de borrador existente si aparece
await declaracion.manejarDialogoConfirmacion('NO');
await declaracion.btnSiguienteAnio.click();

// Paso 2: Establecimientos — avanzar sin modificar
await declaracion.avanzarDesdeEstablecimientos();

// Paso 3: Liquidación de conceptos
await declaracion.completarSeccion3({
  compras: '5000000',
  servicios: '3000000',
  industria: '1000000',
});
await declaracion.actualizarLiquidacion();
await declaracion.avanzarDesdeLiquidacion();

// Paso 4: Declaración — diálogo Terceros asociados
await declaracion.verificarDialogoTercerosVisible();
await declaracion.completarDatosDeclarante({
  tipoDeclarante: 'Representante Legal',
  tipoDocumento: 'CC',
  numeroDocumento: '12345678',
  nombres: 'JUAN PEREZ GARCIA',
});
await declaracion.guardarTercerosAsociados();

// Verificar que el wizard completó todos los pasos
await declaracion.verificarTabActiva('Declaración');
Usa avanzarDesdeAnioGravable(datos, respuestaConfirmacion) como shortcut que encadena completarSeccion1() + manejarDialogoConfirmacion() + el click en Siguiente en una sola llamada. El parámetro respuestaConfirmacion acepta 'SI' (usar borrador existente) o 'NO' (crear declaración nueva).

Build docs developers (and LLMs) love