Saltar al contenido principal

Modos de Reportes en iDempiere

· 13 min de lectura
Luis Amesty Linares
IT Consultant, Developer and Implementer

Este documento pretende mostrar diversas modalidades de reportes que pueden utilizarse en Idempiere y disponer de flexibilidad a la hora de construir resultados complejo.

Dentro de las tecnicas mas conocidas se tiene:

De estas dos técnicas existe una amplia información en la Wiki de idempiere y en los diversos foros de la comunidad.

No entraremos en detalles sobre estas dos modalidades, sin embargo se mostrarán metodos y procedimientos no convencionales utilizando Jaspersoft, Codigo Java, ZK y librerías de Apache poi, que se detallan en los diferentes técnicas, de las cuales se detallan.

Métodos alternativos de avanzada:

Código fuente se puede encontrar en:

  • iDempiere (fuente): https://github.com/idempiere/idempiere
  • Localizaciones y plugins: https://github.com/luisamesty/Amerpsoft-iDempiere-lve/tree/release-12

Framework Propio

La técnica o framework propio de iDempiere para la creación de reportes y documentos (como facturas, órdenes de compra, etc.) se llama Application Dictionary Reporting o ADempiere Reporting Engine.


⚙️ Concepto y Componentes

Este motor de reportes no se basa en un lenguaje de scripting como Groovy (usado por JasperReports), sino que utiliza la propia estructura de metadatos del Diccionario de Aplicación (AD) de iDempiere.

Los componentes clave de esta técnica son:

  1. Report & Process (Proceso y Reporte): Define la lógica de negocio (en Java) para obtener los datos. Esta clase se asocia a una ventana de parámetros (Report & Process / Proceso y Reporte).
  2. Report View (Vista de Reporte): Es una vista de base de datos (AD_RV_...) que consolida los datos necesarios para el reporte. Esta vista es crucial, ya que el motor de reportes del AD opera directamente sobre ella.
  3. Print Format (Formato de Impresión): Este es el corazón de la técnica. Permite diseñar el diseño del reporte (campos, etiquetas, agrupaciones, totales) completamente desde la interfaz de usuario de iDempiere, sin tocar código ni archivos externos (XML/JRXML).

En resumen, la técnica propia es la configuración de Print Formats sobre Report Views, controlada por la lógica de un Process en el Diccionario de Aplicación.

Distinción Importante

Cuando se habla de la "técnica propia" de iDempiere, se refiere al diseño a través del Print Format del Diccionario de Aplicación.

📄 Jaspersoft

Resumen de Reportes en iDempiere con Jaspersoft

La integración de Jaspersoft (o JasperReports) en iDempiere es el mecanismo estándar para crear reportes con diseño complejo, visualización avanzada, gráficos, y salida PDF/Excel/HTML profesional. Es el motor utilizado para la mayoría de los documentos transaccionales y reportes financieros avanzados, complementando el motor de reportes propio del Diccionario de Aplicación (AD).

↑ Volver al Inicio


Jaspersoft - Proceso de Integración

El flujo para crear y usar un reporte Jaspersoft en iDempiere involucra dos mundos principales: el diseño externo y la configuración interna de iDempiere.

1. Diseño del Reporte (Entorno Externo)

Se utiliza la herramienta de diseño de JasperReports (típicamente Jaspersoft Studio):

  • JRXML: El diseñador crea el archivo .jrxml, que es el código fuente XML que define el diseño, la colocación de campos, las fuentes, los gráficos y los estilos.
  • Fuente de Datos: El diseñeador usa una consulta SQL o una Report View (AD_RV_...) para obtener los datos de iDempiere. La consulta debe ser compatible con la estructura de la base de datos de iDempiere.
  • Compilación: El archivo .jrxml se compila en un archivo binario .jasper (el reporte listo para ser ejecutado) que luego se carga en iDempiere.

2. Configuración en iDempiere (Diccionario de Aplicación - AD)

Para que iDempiere ejecute y muestre el reporte, el archivo .jasper debe registrarse y asociarse a un proceso:

ComponenteConfiguraciónPropósito
Proceso y Reporte (AD_Process)Se crea un nuevo proceso (Action = P).Define la ventana de parámetros del usuario (filtros).
ParámetrosSe definen los campos de filtro que se enviarán a Jasper (ej. C_BPartner_ID, DateFrom).Permite la interactividad con el usuario.
Formato de Impresión (AD_PrintFormat)Se asocia el AD_Process con un AD_PrintFormat.Este es el contenedor donde se adjunta el archivo .jasper.
Archivo .jasperSe carga el archivo compilado (.jasper) en el campo Jasper Report del PrintFormat.Vincula el diseño externo con la ejecución interna.

Jaspersoft - Ejecución y Visualización

Cuando el usuario selecciona la opción de menú asociada al proceso:

  1. iDempiere ejecuta la lógica del proceso (si existe).
  2. Recoge los parámetros de entrada del usuario.
  3. Ejecuta la consulta SQL definida en el reporte .jasper, enviando los parámetros (P_DateFrom, P_OrgID, etc.).
  4. El motor de JasperReports genera la salida (PDF, XLSX, etc.).
  5. El resultado se muestra en el Visor de Jasper (ZkJRViewer), el cual se abre en una nueva pestaña (GridTab) de la aplicación iDempiere.

↑ Volver al Inicio


🧩 Jasper Java Class Pojo

Este reporte de ejemplo muestra los elementos de cuenta configurados para un cliente específico dentro del esquema contable.

Se basa en una Clase Java POJO. Lee los datos de la base de datos utilizando una Clase Java DataPopulator.

El archivo: src/org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_Pojo.jrxml no está adjunto a un Proceso AD, sino que se lee directamente desde el sistema de archivos (Filesystem).

Los parámetros se leen desde SvrProcess y se inyectan en el archivo de Jaspersoft.

Configuración del Proceso en el Diccionario de Aplicaciones (AD)

Para que este reporte de Java Class POJO sea ejecutable desde el menú de iDempiere, debes registrarlo como un Proceso y/o Reporte. Y posteriomente añadir una entrada de menu a este proceso.

Crear Proceso

Campo de la Ventana "Proceso y Reporte"Valor
Nombre (Name)Amfin Account Elements Jasper Java Class Pojo
Valor de Búsqueda (Value)AmfinAccountElementsJasperJavaClassPo
Clase (Classname)org.amerp.reports.jasper.AccountElements_Tree.AccountElements_Tree_Pojo
Tipo de ProcedimientoJava
Reporte(Marcar la casilla)

Parámetros

ParámetroCódigo / ColumnaExplicación Detallada
Cliente / Grupo empresarialAD_Client_IDEste parámetro es fundamental para la seguridad y el alcance de los datos. Limita la ejecución del informe a la información que pertenece exclusivamente a la empresa o al grupo de empresas seleccionado. En un entorno multi-tenant, esto garantiza que solo se procesen los elementos de cuenta de la organización correcta.
Esquema ContableC_AcctSchema_IDEs el parámetro más crucial para definir la estructura del informe. El esquema contable es la plantilla que determina la forma en que una organización registra sus transacciones. Al seleccionarlo, el reporte sabe qué: • Plan de Cuentas (Chart of Accounts) usar. • Reglas contables (ej. devengo vs. caja). • Moneda base y elementos (cuentas, dimensiones) que deben incluirse en el informe.

Pantalla Parámetros

Toma de parametros

Clase Java

File: AccountElements_Tree_Pojo.java

La clase Java es un SvrProcess clásico:

public class AccountElements_Tree_Pojo extends SvrProcess implements ProcessCall, ClientProcess{

Preparación de Parámetros (prepare()):

    @Override
protected void prepare() {
ProcessInfoParameter[] para = getParameter();
for (ProcessInfoParameter pp : para) {
String name = pp.getParameterName();
if (name.equals("AD_Client_ID")) {
p_AD_Client_ID = pp.getParameterAsInt();
} else if (name.equals("C_AcctSchema_ID")) {
p_C_AcctSchema_ID = pp.getParameterAsInt();
}
}
// Si no se pasaron como parámetro, obtener del contexto actual de iDempiere
if (p_AD_Client_ID == 0) {
p_AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
}
// Para C_AcctSchema_ID, si no viene como parámetro, podría requerir lógica para obtener el predeterminado
// o ser un parámetro obligatorio en la ventana del proceso. Aquí lo dejamos como 0 si no se pasa.
}

Generación del Reporte (doIt()):

A continuación, se describen los pasos clave dentro del método doIt() (ejecutar):

  • Paso 0: Copiar archivos al directorio temporal en el servidor.
      // Lista de recursos a copiar
String[] resourcesToCopy = new String[]{
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_Pojo.jrxml",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree.properties",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_es.properties",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_fr.properties"
// Si hay imágenes o subreports, añádelos aquí
};
for (String resource : resourcesToCopy) {
jasperUtils.copyResourceToTmp(resource, tmpFolder);
}
  • Paso 1: Obtener los datos para el informe desde la clase DataPopulator.
      // Lista de recursos a copiar
String[] resourcesToCopy = new String[]{
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_Pojo.jrxml",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree.properties",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_es.properties",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_fr.properties"
// Si hay imágenes o subreports, añádelos aquí
};
for (String resource : resourcesToCopy) {
jasperUtils.copyResourceToTmp(resource, tmpFolder);
}
  • Paso 2: Compilar el archivo Jasper.
        try (InputStream reportStream = new FileInputStream(jrxmlPath)) {
jasperReport = JasperCompileManager.compileReport(reportStream);
log.info("Archivo .jasper cargado exitosamente.");
} catch (Exception e) {
log.log(Level.SEVERE, "Error al cargar y/o compilar el archivo .jrxml desde: " + jrxmlPath, e);
throw e; // Relanza la excepción para que iDempiere la maneje
}
  • Paso 3: Crear JRBeanCollectionDataSource (Fuente de datos basada en una colección de beans).
        JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(reportData);
log.info("JRBeanCollectionDataSource creado con " + dataSource.getRecordCount() + " registros.");
  • Paso 4: Preparar los Parámetros del informe.
        Map<String, Object> parameters = new HashMap<>();
parameters.put("AD_Client_ID", p_AD_Client_ID);
parameters.put("C_AcctSchema_ID",p_C_AcctSchema_ID);
parameters.put(JRParameter.REPORT_RESOURCE_BUNDLE, ResourceBundle.getBundle(
"org.amerp.reports.jasper.AccountElements_Tree.AccountElements_Tree",
Locale.getDefault()
));
  • Paso 5: Rellenar el informe (Fill report) y llamar al visor JRViewer.
        try {
jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
log.info("Informe de JasperReports llenado exitosamente.");
} catch (JRException e) {
log.log(Level.SEVERE, "Error al llenar el informe de JasperReports.", e);
throw e; // Relanza la excepción
}
....
try (Connection conn = DB.getConnectionRO()) {
// export to viewer
processInfo = getProcessInfo();
printInfo = new PrintInfo(processInfo);
// view the report
JRViewerProvider viewerLauncher = Service.locator().locate(JRViewerProvider.class).getService();
viewerLauncher.openViewer(jasperPrint, processInfo.getTitle(), printInfo);
}

Ejemplo reporte

Reporte

↑ Volver al Inicio


📄 Jasper Java Class Standard

Este reporte de ejemplo muestra los elementos de cuenta configurados para un cliente específico dentro del esquema contable.

Se basa en una Clase Java Std. Lee los datos utilizando una Consulta SQL definida dentro del archivo .jrxml.

El archivo: src/org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_Std.jrxml no está adjunto a un Proceso AD, sino que se lee directamente desde el sistema de archivos (Filesystem).

Los parámetros se leen desde SvrProcess y se inyectan en el archivo de Jaspersoft.

Configuración del Proceso en el Diccionario de Aplicaciones (AD)

Para que este reporte de Clase Java Estándar sea ejecutable desde el menú de iDempiere/ADempiere, debes registrarlo como un Proceso y/o Reporte en el Diccionario de Aplicaciones. Y posteriomente añadir una entrada de menu a este proceso.


Crear el Proceso

Campo de la Ventana "Proceso y Reporte"Valor
Nombre (Name)Amfin Account Elements Jasper Java Class Standard
Valor de Búsqueda (Value)AmfinAccountElementsJasperJavaClassStd
Clase (Classname)org.amerp.reports.jasper.AccountElements_Tree.AccountElements_Tree_Std
Tipo de ProcedimientoJava
Reporte(Marcar la casilla)

Parámetros

  • Cliente / Tenant (AD_Client_ID): Se refiere a la empresa o grupo de empresas que comparten la misma configuración contable.
  • Esquema Contable (C_AcctSchema_ID): Define la estructura contable, incluyendo plan de cuentas, reglas, monedas y otras configuraciones financieras.

El informe puede incluir filtros basados en niveles de cuenta, tipos de cuenta o estado (activo/inactivo), dependiendo del esquema contable seleccionado.

Pantalla Parámetros

Toma de parametros

Clase Java

File: AccountElements_Tree_Std.java

La clase Java es un SvrProcess clásico:

public class AccountElements_Tree_Std extends SvrProcess implements ProcessCall, ClientProcess {

Preparación de Parámetros (prepare()):

        for (ProcessInfoParameter param : pip) {
String name = param.getParameterName();
if (param.getParameter() == null)
;
else if ("AD_Client_ID".equalsIgnoreCase(name))
p_AD_Client_ID = param.getParameterAsInt();
else if ("C_AcctSchema_ID".equalsIgnoreCase(name))
p_C_AcctSchema_ID = param.getParameterAsInt();
else
log.severe("Unknown Parameter: " + name);
}

Generación del Reporte (doIt()):

  • Paso 0: Copiar archivos al directorio temporal en el servidor.
        // Carpeta temporal
JasperUtils jasperUtils = new JasperUtils();
String tmpFolder = jasperUtils.getTempFolder();
// Lista de recursos a copiar
String[] resourcesToCopy = new String[]{
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_Std.jrxml",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree.properties",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_es.properties",
"org/amerp/reports/jasper/AccountElements_Tree/AccountElements_Tree_fr.properties"
// Si hay imágenes o subreports, añádelos aquí
};
// Copiar físicamente cada recurso al tmpFolder
for (String resource : resourcesToCopy) {
jasperUtils.copyResourceToTmp(resource, tmpFolder);
}
  • Paso 1: Obtener Parámetros.
        try (InputStream reportStream = new FileInputStream(jrxmlPath)) {
JasperReport jasperReport = JasperCompileManager.compileReport(reportStream);

// Parámetros, conexión, etc.
Map<String, Object> parameters = new HashMap<>();
parameters.put("AD_Client_ID", p_AD_Client_ID);
parameters.put("C_AcctSchema_ID",p_C_AcctSchema_ID);
parameters.put(JRParameter.REPORT_RESOURCE_BUNDLE, ResourceBundle.getBundle(
"org.amerp.reports.jasper.AccountElements_Tree.AccountElements_Tree",
Locale.getDefault()
));
  • Paso 2: Compilar, generar y desplegar el archivo Jasper.
            try (Connection conn = DB.getConnectionRO()) {
jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn);
// export to viewer
processInfo = getProcessInfo();
printInfo = new PrintInfo(processInfo);
// view the report
JRViewerProvider viewerLauncher = Service.locator().locate(JRViewerProvider.class).getService();
viewerLauncher.openViewer(jasperPrint, processInfo.getTitle(), printInfo);
}

Ejemplo de reporte

Reporte

↑ Volver al Inicio


📄 Process Class Xlsx

Este reporte de ejemplo muestra los elementos de cuenta configurados para un cliente específico dentro del esquema contable.

Se basa en una Clase Java que utiliza clases Apache POI XLSX para generar un Archivo XLSX. Lee los datos de la Base de Datos utilizando una Clase Java DataPopulator.

El informe se muestra dentro de una ventana de visualización XLSX, lo que permite a los usuarios explorar fácilmente filas y columnas en detalle. También ofrece la opción de descargar el archivo para verlo en Excel o LibreOffice.

Archivos y Proceso

  • Clase principal:org.amerp.reports.xlsx.AccountElements_Tree_ProcXlsx: Clase principal que implementa ProcessCall y ClientProcess. Lee los parámetros del Proceso AD definido.
  • Visor:src/org/amerp/reports/xlsx/ExcelViewerWindow.java: Visor para el archivo Xlsx.
  • Nombre Proceso AD: Amfin Account Elements Process Class Xlsx.

Los parámetros se leen del Proceso AD asociado y se inyectan en el archivo de la clase principal.

Configuración del Proceso en el Diccionario de Aplicaciones (AD)

Para que este reporte de Proceso Java Xlsx sea ejecutable desde el menú de iDempiere/ADempiere, debes registrarlo como un Proceso y/o Reporte en el Diccionario de Aplicaciones. Y posteriomente añadir una entrada de menu a este proceso.

Crear el Proceso

Campo de la Ventana "Proceso y Reporte"Valor
Nombre (Name)Amfin Account Elements Process Class Xlsx
Valor de Búsqueda (Value)AmfinAccountElementsJavaProcXlsx
Clase (Classname)org.amerp.reports.xlsx.AccountElements_Tree_ProcXlsx
Tipo de ProcedimientoJava
Reporte(Marcar la casilla)

Parámetros

  • Cliente / Tenant (AD_Client_ID): Se refiere a la empresa o grupo de empresas que comparten la misma configuración contable.
  • Esquema Contable (C_AcctSchema_ID): Define la estructura contable, incluyendo plan de cuentas, reglas, monedas y otras configuraciones financieras.

El informe puede incluir filtros basados en niveles de cuenta, tipos de cuenta o estado (activo/inactivo), dependiendo del esquema contable seleccionado.

Pantalla Parámetros

Toma de parametros

Clase Java

File: AccountElements_Tree_ProcXlsx.java

La clase Java es una clásica llamada a Proceso (Process Call).

public class AccountElements_Tree_ProcXlsx implements ProcessCall, ClientProcess {

Iniciar Proceso (startProcess(...)):

  • Paso 1: Crea el Xlsx (crearXlsx(..))
        try {
// Aquí generas tu Excel
File xlsxFile = crearXlsx(ctx, pInfo, null);
if (xlsxFile == null)
return false;
final String fullPath = xlsxFile.getAbsolutePath();
pInfo.setSummary("Archivo generado: " + fullPath);
  • Paso 2: Previsualizar Xlsx (previewXlsx(xlsxFile))
             if (m_processUI != null && xlsxFile != null) {
previewXlsx(xlsxFile);
}

Crear XLsx (crearXlsx(...)):

En este caso particular, utiliza la librería Apache POI Xlsx.

  • Importaciones importantes:
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.*;
import org.amerp.reports.xlsx.util.ExcelUtils;
  • Método importante del Visor (openExcelViewerInNewTab(File xlsxFile)):

Utiliza atributos especiales del visor ZK WebUI para desplegar el archivo Xlsx en una pestaña (TAB) de iDempiere.

    private void openExcelViewerInNewTab(File xlsxFile) {
try {
// 🖥️ Obtener el escritorio activo
IDesktop desktop = SessionManager.getAppDesktop();

if (desktop != null) {
ExcelViewerWindow viewer = new ExcelViewerWindow(
xlsxFile,
headers,
maxLen,
4,
50000
); // tu constructor

viewer.setAttribute(Window.MODE_KEY, Window.MODE_EMBEDDED);
viewer.setAttribute(Window.INSERT_POSITION_KEY, Window.INSERT_NEXT);
viewer.setAttribute(WindowContainer.DEFER_SET_SELECTED_TAB, Boolean.TRUE);

desktop.registerWindow(viewer);
desktop.showWindow(viewer);
//AEnv.showCenterScreen(viewer);
}

log.info("✅ Visor Excel abierto en nuevo tab: " + xlsxFile.getAbsolutePath());
} catch (Exception e) {
log.warning( "❌ Error al abrir formulario de visor Excel\n\r"+e.getMessage());
}
}

Ejemplo reporte

Reporte

↑ Volver al Inicio