Su Template de Datos del Registro al Informe - Asientos Contables
Su Template de Datos del Registro al Informe - Asientos Contables
- Atributos recomendados para recopilar
- Actividades clave para el seguimiento
- Guía práctica de extracción
Atributos del Registro al Informe - Asientos Contables
| Nombre | Descripción | ||
|---|---|---|---|
| Actividad ActivityName | El nombre de la actividad de negocio que ocurrió en un punto específico del proceso de asientos contables. | ||
| Descripción La Actividad representa un paso o Analizar las actividades permite visualizar el flujo del proceso, identificar rutas comunes y descubrir desviaciones del procedimiento estándar. Es fundamental para calcular métricas como la frecuencia de actividad, los Por qué es importante Define los pasos del proceso, permitiendo la visualización de mapas de proceso y el análisis de patrones de workflow. Dónde obtener Derivado de varias fuentes, incluyendo campos de estado en tablas de cabecera/partida (ej. BKPF-BSTAT), registros de documentos de cambio (CDHDR/CDPOS) y registros de workflow. Ejemplos Asiento Contable CreadoAsiento Contable EstacionadoAsiento Enviado para RevisiónAsiento Contable AprobadoAsiento Contable Contabilizado | |||
| Hora del Evento EventTime | La `timestamp` que indica cuándo ocurrió una actividad específica para el asiento contable. | ||
| Descripción El Tiempo del Evento es la fecha y hora precisas en que una actividad de negocio fue ejecutada y registrada en el sistema. Cada actividad en un caso tiene su propia marca de tiempo, creando una secuencia cronológica de eventos. Este atributo es crítico para todo análisis de procesos basado en el tiempo. Se utiliza para calcular tiempos de ciclo, duraciones entre actividades, tiempos de espera y para comprender la distribución temporal del trabajo. Las marcas de tiempo precisas son esenciales para construir un modelo de proceso fiable y calcular indicadores clave de rendimiento como el Tiempo de Ciclo de Aprobación. Por qué es importante Proporciona el orden cronológico de los eventos, lo cual es esencial para calcular todas las métricas basadas en la duración y comprender la línea de tiempo del proceso. Dónde obtener Obtenido de los registros de documentos de cambio (CDHDR-UDATE, CDHDR-UTIME), registros de Ejemplos 2023-10-26T10:05:00Z2023-11-15T14:30:15Z2024-01-20T09:00:45Z | |||
| ID de Asiento Contable JournalEntryId | El identificador único para un asiento contable financiero, que sirve como identificador principal del `case` para el proceso. | ||
| Descripción El ID de Asiento Contable es un número único asignado a cada documento contable al crearse en SAP S/4HANA. Este identificador es esencial para rastrear el ciclo de vida completo de un asiento contable, desde su creación o estacionamiento inicial, a través de En el análisis de Por qué es importante Este identificador conecta todos los pasos del proceso relacionados, haciendo posible analizar el recorrido de principio a fin de cada asiento contable. Dónde obtener Esta es una clave compuesta, típicamente formada por la concatenación de la Sociedad (BKPF-BUKRS), el Número de Documento (BKPF-BELNR) y el Ejercicio Fiscal (BKPF-GJAHR). Ejemplos 1000-1000000001-20231710-1900000055-20242000-2100003412-2023 | |||
| Creado Por Usuario CreatedByUser | El ID de usuario de la persona que creó el asiento contable. | ||
| Descripción Este Analizar el proceso por el creador ayuda a identificar patrones relacionados con usuarios o equipos específicos. Puede revelar necesidades de capacitación si ciertos usuarios tienen tasas de rechazo más altas, o destacar individuos de alto rendimiento. Es esencial para el Por qué es importante Atribuye las actividades del proceso a usuarios específicos, lo que permite el análisis del rendimiento, el equilibrio de la carga de trabajo y la identificación de oportunidades de capacitación. Dónde obtener Tabla SAP S/4HANA BKPF, campo USNAM (Nombre de Usuario). Ejemplos ABROWNCJONESBATCH_USER | |||
| Fecha de Contabilización PostingDate | La fecha en la que el asiento contable se registra en el Libro Mayor, afectando el período financiero. | ||
| Descripción La Fecha de Contabilización determina el período fiscal en el que la transacción aparecerá en los estados financieros. Es una fecha crítica para la contabilidad y puede diferir de la fecha en que el documento fue creado o ingresado al sistema. En el Por qué es importante Crucial para el contexto financiero, permite analizar el rendimiento del proceso dentro de períodos contables específicos, como el cierre de mes o el cierre de año. Dónde obtener Tabla SAP S/4HANA BKPF, campo BUDAT (Fecha de Contabilización en el Documento). Ejemplos 2023-10-312023-11-012024-02-29 | |||
| Importe en Moneda Local AmountInLocalCurrency | El valor total del asiento contable expresado en la moneda local de la sociedad. | ||
| Descripción Este Analizar por importe permite la segmentación del proceso basada en el impacto financiero. Por ejemplo, los asientos de alto valor pueden seguir un proceso de aprobación más riguroso que los de bajo valor. Ayuda a priorizar los esfuerzos de mejora del proceso en transacciones que presentan el mayor riesgo financiero. Por qué es importante Proporciona el valor financiero del asiento, lo que permite analizar cómo cambia el comportamiento del proceso con el valor monetario en juego. Dónde obtener Calculado sumando los importes de la tabla de partidas individuales BSEG (campo DMBTR) para un asiento contable dado (BELNR) y convirtiendo el resultado a un valor positivo. Ejemplos 1500.75125000.0050.20 | |||
| Sociedad CompanyCode | El identificador único de la sociedad o entidad legal para la cual se contabiliza el asiento contable. | ||
| Descripción La Sociedad es una unidad organizativa fundamental en SAP Financials, que representa una entidad legal independiente para la cual se generan estados financieros. Cada asiento contable se asigna a una sociedad específica. Este Por qué es importante Permite filtrar y comparar el proceso de asientos contables entre diferentes entidades legales o unidades de negocio dentro de la organización. Dónde obtener Tabla SAP S/4HANA BKPF, campo BUKRS (Sociedad). Ejemplos 10001710US01 | |||
| Tipo de Asiento Contable JournalEntryType | Clasifica el asiento contable según su propósito de negocio, como una contabilización de activo, una factura de proveedor o un asiento de libro mayor. | ||
| Descripción El Tipo de Asiento Contable, o Tipo de Documento en la terminología de SAP, es una clave que categoriza los documentos contables. Controla Analizar el proceso por tipo de asiento contable es crucial para comprender comportamientos específicos del contexto. Por ejemplo, el proceso de aprobación para un simple devengo (tipo SA) puede ser mucho más sencillo que para una adquisición compleja de Por qué es importante Categoriza las entradas por contexto de negocio, lo que permite el análisis de las variaciones del proceso y el rendimiento para diferentes tipos de transacciones financieras. Dónde obtener Tabla SAP S/4HANA BKPF, campo BLART (Tipo de Documento). Ejemplos SAKRAA | |||
| ¿Es Retrabajo? IsRework | Un indicador booleano que señala si el asiento contable ha sido retrabajado, por ejemplo, corregido después de un rechazo. | ||
| Descripción Este Esta bandera simplifica el análisis de la eficiencia del proceso. Permite el cálculo rápido del KPI de Tasa de Retrabajo y permite la comparación directa de los Por qué es importante Marca los casos que requirieron corrección o bucles adicionales, lo que permite una fácil cuantificación y análisis de la causa raíz de las ineficiencias del proceso. Dónde obtener Este es un Ejemplos truefalse | |||
| Código de Transacción TransactionCode | El código de transacción SAP utilizado para crear o cambiar el asiento contable. | ||
| Descripción El Código de Transacción (T-Code) es un atajo que identifica una función o programa específico en SAP. Para los asientos contables, diferentes T-Codes pueden indicar cómo se creó el asiento, por ejemplo, FB01 para la contabilización manual en el libro mayor, FV50 para el estacionamiento, o un código automatizado para entradas generadas por el sistema. Este Por qué es importante Indica cómo se procesó una entrada (ej., manual vs. automáticamente), lo cual es clave para el análisis de la automatización y la comprensión de las variaciones del proceso. Dónde obtener Tabla SAP S/4HANA BKPF, campo TCODE (Código de Transacción). Ejemplos FB01FV50F-02 | |||
| Ejercicio Fiscal FiscalYear | El ejercicio fiscal al que pertenece el asiento contable. | ||
| Descripción El Ejercicio Fiscal es parte de la clave única para un asiento contable, junto con la sociedad y el número de documento. Representa el año financiero en el que el documento es relevante. En el análisis, el ejercicio fiscal se utiliza para el análisis de tendencias a largo plazo y para asegurar la unicidad del identificador de Por qué es importante Proporciona un componente crítico para identificar documentos de forma única y permite el análisis del rendimiento del proceso año tras año. Dónde obtener Tabla SAP S/4HANA BKPF, campo GJAHR (Ejercicio Fiscal). Ejemplos 202320242022 | |||
| Es Contabilización Manual IsManualPosting | Un indicador booleano que señala si el asiento contable fue contabilizado manualmente por un usuario. | ||
| Descripción Este Esta bandera se utiliza para calcular el KPI de Tasa de Contabilización Manual y ayuda a las organizaciones a seguir su progreso en la automatización del proceso del Registro al Informe. Al filtrar los asientos contabilizados manualmente, los analistas pueden identificar los escenarios específicos que aún requieren intervención humana y evaluarlos para el potencial de automatización. Por qué es importante Diferencia entre contabilizaciones realizadas por humanos y por el sistema, lo cual es crítico para medir los niveles de automatización e identificar oportunidades de automatización. Dónde obtener Este es un Ejemplos truefalse | |||
| Estado del Documento DocumentStatus | El estado de procesamiento actual del asiento contable, como Estacionado, Contabilizado o Compensado. | ||
| Descripción El Estado del Documento indica el estado del asiento contable dentro de su ciclo de vida. Por ejemplo, un documento "estacionado" se guarda pero aún no se ha contabilizado en el Libro Mayor, mientras que un documento "contabilizado" está finalizado. Analizar el estado ayuda a comprender el flujo de trabajo e identificar Por qué es importante Proporciona una instantánea de dónde se encuentra un asiento contable en su ciclo de vida, ayudando a identificar colas y Dónde obtener Tabla SAP S/4HANA BKPF, campo BSTAT (Estado del documento). Ejemplos VAB | |||
| Hora de Finalización EndTime | La `marca de tiempo` que indica cuándo se completó la `actividad`. | ||
| Descripción La Hora de Fin marca la finalización de una actividad. En muchos Tener una Hora de Fin distinta permite un cálculo más preciso de los Por qué es importante Permite el cálculo de tiempos de procesamiento precisos de las actividades, separando el tiempo de trabajo activo del tiempo de espera inactivo. Dónde obtener Típicamente igual que StartTime para Ejemplos 2023-10-26T10:05:00Z2023-11-15T14:45:20Z2024-01-20T09:10:30Z | |||
| Motivo de Reversión ReversalReason | Un código que indica el motivo por el cual un asiento contable ya contabilizado fue anulado. | ||
| Descripción Cuando un asiento contable contabilizado es incorrecto, no se puede eliminar, sino que debe anularse con un nuevo documento. El código de Motivo de Anulación explica por qué se tomó esta acción, por ejemplo, debido a una fecha de contabilización o un importe incorrectos. Analizar los motivos de anulación ayuda a identificar las causas raíz de los errores en el proceso del Registro al Informe. Una alta frecuencia de un motivo particular puede apuntar a problemas sistémicos, como capacitación inadecuada o fallas en el control, que deben abordarse para mejorar la calidad desde el primer momento. Por qué es importante Ayuda a diagnosticar la causa raíz de los errores que conducen a anulaciones, proporcionando los insights necesarios para reducir el retrabajo y mejorar la calidad del proceso. Dónde obtener Tabla SAP S/4HANA BKPF, campo STGRD (Motivo de anulación). Ejemplos 010205 | |||
| Source System SourceSystem | Identifica el sistema de origen del cual se extrajeron los datos del asiento contable. | ||
| Descripción Este En el análisis, puede utilizarse para comparar el rendimiento del proceso en diferentes sistemas o para filtrar Por qué es importante Proporciona contexto sobre el origen de los Dónde obtener Este es típicamente un valor estático añadido durante la extracción de Ejemplos S4H_PROD_100ECC_FIN_200S4C_US_EAST | |||
| Tiempo de Ciclo Total TotalCycleTime | La duración total desde la creación de la primera actividad hasta la finalización de la última actividad para un asiento contable. | ||
| Descripción Esta métrica calculada mide la duración de principio a fin del proceso de asiento contable para cada El Tiempo Total del Ciclo es un KPI primario para medir la eficiencia general del proceso. Proporciona una vista de alto nivel del rendimiento del proceso y se utiliza en Por qué es importante Mide la duración del proceso de principio a fin, proporcionando un indicador clave de rendimiento para la eficiencia y velocidad general del proceso. Dónde obtener Calculado restando el EventTime mínimo del EventTime máximo para cada JournalEntryId único. Ejemplos 2 días 4 horas 30 minutos8 horas 15 minutos15 días 2 horas | |||
| Tiempo del Ciclo de Aprobación ApprovalCycleTime | El `tiempo` transcurrido desde que un asiento contable fue enviado para aprobación hasta que fue aprobado o rechazado. | ||
| Descripción Esta métrica calculada se centra específicamente en la duración de la etapa de aprobación. Mide el Este KPI es crítico para identificar Por qué es importante Aísla la duración del paso de aprobación, ayudando a identificar y abordar los cuellos de botella en el workflow de revisión y aprobación. Dónde obtener Calculado al encontrar la diferencia de tiempo entre el evento 'Asiento Enviado para Revisión' y el evento 'Asiento Contable Aprobado' o 'Asiento Contable Rechazado'. Ejemplos 1 día 2 horas4 horas 25 minutos5 días 0 horas | |||
| Última actualización de datos LastDataUpdate | Marca de tiempo que indica la última vez que se actualizaron los datos de este registro desde el sistema de origen. | ||
| Descripción Este Conocer la última Por qué es importante Indica la frescura de los datos, asegurando que los usuarios sean conscientes de cuán actual es el análisis del proceso. Dónde obtener Este es un Ejemplos 2024-03-10T02:00:00Z2024-03-11T02:00:00Z2024-03-12T02:00:00Z | |||
| Usuario Aprobador ApproverUser | El ID de usuario de la persona que aprobó o rechazó el asiento contable. | ||
| Descripción Este Esta información es esencial para analizar el proceso de aprobación en detalle. Ayuda a medir la carga de trabajo de diferentes aprobadores, calcular los Por qué es importante Identifica al individuo responsable de la aprobación, lo que permite el análisis de las cargas de trabajo de aprobación, el rendimiento y los cuellos de botella. Dónde obtener Obtenido de los registros de Ejemplos DMILLERFWHITEKCHEN | |||
Actividades del Registro al Informe - Asientos Contables
| Actividad | Descripción | ||
|---|---|---|---|
| Anulación de Asiento Contable Procesada | Un asiento contable previamente contabilizado se anula creando un nuevo documento con contabilizaciones inversas. Esta acción se realiza para corregir errores en documentos contabilizados y es una transacción explícita y auditable. | ||
| Por qué es importante Las anulaciones indican que se cometió un error en un documento contabilizado. Una alta tasa de anulaciones sugiere problemas subyacentes en el proceso de aprobación o en la calidad de la entrada de Dónde obtener La anulación es un Capturar Identifique documentos donde BKPF-STBLG esté relleno. La fecha/hora del evento es la fecha de contabilización del documento de anulación. Tipo de evento explicit | |||
| Asiento Contable Aprobado | El asiento contable recibe la aprobación final de un gerente autorizado, confirmando su validez y precisión. Esta actividad es la puerta final antes de que el documento pueda ser contabilizado en el libro mayor. | ||
| Por qué es importante Este es un hito crítico que concluye el ciclo de aprobación. El Dónde obtener Este Capturar Identifique la fecha/hora del paso de aprobación final en los registros de workflow o el cambio de estado a 'Aprobado' en los documentos de cambio. Tipo de evento inferred | |||
| Asiento Contable Compensado | Una partida abierta dentro de un asiento contable es compensada por otra contabilización, como un pago que liquida una factura. Esta actividad marca la conciliación de partidas individuales específicas, cerrándolas efectivamente. | ||
| Por qué es importante Esta actividad representa el paso final de conciliación para muchos asientos contables, especialmente aquellos que involucran cuentas transitorias o de partidas abiertas. Analizar el Dónde obtener Este Capturar Use la fecha de compensación (BSEG-AUGDT) para la partida individual como Tipo de evento inferred | |||
| Asiento Contable Contabilizado | El asiento contable se registra oficialmente en el libro mayor, afectando los estados financieros de la empresa. Este es el punto en el que el documento se convierte en un registro financiero permanente. | ||
| Por qué es importante Este es el hito principal de éxito, que marca el final del ciclo de procesamiento principal. Analizar el rendimiento de las entradas contabilizadas y el Dónde obtener Este es un Capturar Use la Fecha de Contabilización (BKPF-BUDAT) y la Fecha de Entrada (BKPF-CPUDT) para registrar el Tipo de evento explicit | |||
| Asiento Contable Creado | Esta actividad marca la creación inicial de un documento de asiento contable en el sistema. El registro se crea en la tabla de cabecera (BKPF), pero aún no se ha contabilizado en el libro mayor. Este es el punto de partida para el ciclo de vida del asiento contable. | ||
| Por qué es importante Este es el Dónde obtener Este Capturar Use BKPF-CPUDT y BKPF-CPUTM para la Tipo de evento explicit | |||
| Asiento Enviado para Revisión | El creador del asiento contable envía formalmente el documento para el `workflow` de revisión y aprobación. Esta actividad representa la transferencia de la entrada de `datos` al proceso de control formal, iniciando el ciclo de aprobación. | ||
| Por qué es importante Esto marca el inicio del Dónde obtener Esto a menudo se captura de los registros de Capturar
Tipo de evento inferred | |||
| Asiento Contable Corregido | El usuario modifica un asiento contable después de que fue rechazado o devuelto para cambios. Esto representa el esfuerzo de retrabajo requerido para abordar los problemas identificados durante el proceso de revisión antes de la nueva presentación. | ||
| Por qué es importante Esta actividad cuantifica los bucles de retrabajo. Analizar la frecuencia y duración de las correcciones ayuda a identificar las fuentes de ineficiencia y destaca las oportunidades de capacitación y clarificación de procesos. Dónde obtener Esto se puede inferir rastreando la fecha de "Último Cambio" (AEDAT) en la tabla BKPF para un documento que previamente estaba en estado "Rechazado". Los documentos de cambio proporcionan más detalles específicos sobre lo que se modificó. Capturar Use la Tipo de evento inferred | |||
| Asiento Contable Estacionado | Un usuario guarda un asiento contable incompleto sin contabilizarlo, permitiendo su posterior finalización o revisión. Esta es una acción explícita que crea un registro de cabecera de documento con un estado 'aparcado', manteniéndolo en un estado no contabilizado. | ||
| Por qué es importante El estacionamiento es un paso común antes del envío. Realizar un seguimiento de la duración del estado estacionado ayuda a identificar retrasos en la finalización y preparación de los Dónde obtener En la tabla BKPF, un documento aparcado se identifica por el campo de estado del documento (BSTAT) con un valor de 'V'. La fecha/hora del evento es la fecha de creación (CPUDT). Capturar Filtrar los documentos donde BKPF-BSTAT = 'V' en el momento de la creación. Tipo de evento explicit | |||
| Asiento Contable Modificado Después de la Contabilización | Un usuario modifica un conjunto limitado de campos en un asiento contable después de que ya ha sido contabilizado en el libro mayor. Si bien la mayoría de los datos financieros son inmutables después de la contabilización, algunos campos como el texto o las asignaciones pueden modificarse. | ||
| Por qué es importante Esta actividad es un indicador crítico de Dónde obtener Esto se puede inferir de manera fiable de las tablas de documentos de cambio (CDHDR y CDPOS). Una entrada en CDHDR para el número de documento con una fecha de cambio posterior a la fecha de contabilización significa un cambio posterior a la contabilización. Capturar Encontrar registros en CDHDR donde la fecha/hora de cambio (UDATE/UTIME) sea posterior a la fecha de contabilización del documento (BKPF-BUDAT). Tipo de evento inferred | |||
| Asiento Contable Rechazado | Un revisor o aprobador deniega el asiento contable, impidiendo que sea contabilizado. El documento se envía típicamente de vuelta al creador para su corrección, iniciando un ciclo de retrabajo. | ||
| Por qué es importante El seguimiento de los rechazos es clave para comprender la calidad del proceso e identificar errores comunes. Las altas tasas de rechazo indican problemas con la precisión de los Dónde obtener Este Capturar Identifique el cambio de campo de estado a 'Rechazado' a través de documentos de cambio (CDHDR/CDPOS) o registros de workflow. Tipo de evento inferred | |||
| Contabilización Manual Identificada | El asiento contable se contabilizó utilizando un código de transacción manual en lugar de a través de una interfaz automatizada o un trabajo por lotes. Esto no es un `evento` temporal, sino una clasificación de la actividad de contabilización. | ||
| Por qué es importante Identificar las contabilizaciones manuales es crucial para las iniciativas de automatización. Una alta tasa de contabilizaciones manuales sugiere oportunidades para optimizar procesos mediante la integración de subsistemas o el uso de programas de contabilización automatizados. Dónde obtener Esto se calcula analizando el campo de código de transacción (TCODE) en la tabla de cabecera de documento (BKPF). Se utiliza una lista de T-Codes manuales conocidos (por ejemplo, FB01, F-02, FB50) para clasificar el asiento. Capturar Clasificar el evento basándose en el campo BKPF-TCODE, contrastándolo con una lista predefinida de códigos de transacción manuales en el momento de la contabilización. Tipo de evento calculated | |||
| Documentación de Soporte Adjunta | Un usuario adjunta uno o más documentos de soporte, como facturas u hojas de cálculo, al asiento contable. Esto se realiza típicamente para proporcionar evidencia y contexto para la transacción financiera durante el proceso de revisión y auditoría. | ||
| Por qué es importante Asegurar que la documentación se adjunte antes de la revisión es crítico para el cumplimiento y la eficiencia de la aprobación. Esta actividad ayuda a medir la adhesión a las políticas de documentación y su impacto en los tiempos de ciclo de aprobación. Dónde obtener Esto se infiere típicamente comprobando la Capturar Consulte las tablas de adjuntos GOS (por ejemplo, SRGBTBREL) para enlaces al objeto BKPF y utilice la Tipo de evento inferred | |||
Guías de Extracción
Pasos
- Requisitos Previos y Acceso: Asegúrese de tener un usuario con las autorizaciones necesarias para consultar la base de datos subyacente de SAP S/4HANA o ejecutar informes ABAP. Necesitará acceso de lectura a las vistas CDS I_JournalEntry, I_JournalEntryItem, y a las tablas CDHDR, CDPOS, SRGBREL, SOOD, SWW_WI2OBJ y SWWLOGHIST. El acceso se concede típicamente a través de un cliente de base de datos como SAP HANA Studio, DBeaver, o utilizando las Herramientas de Desarrollo ABAP (ADT) de SAP para Eclipse.
- Identificar Configuraciones Específicas del Sistema: Antes de ejecutar la consulta, debe identificar los códigos de tarea específicos utilizados en su workflow de aprobación de asientos contables. Consulte con su administrador de workflow de SAP para encontrar los IDs de tarea (ej., TS12345678) que corresponden a eventos de envío, rechazo y aprobación. Estos son necesarios para los marcadores de posición en la consulta final.
- Preparar la Consulta SQL: Copie la consulta SQL completa proporcionada en la sección
queryen su cliente SQL o herramienta de desarrollo elegido. - Establecer Parámetros de Consulta: Localice los marcadores de posición dentro de la consulta y reemplácelos con sus valores específicos. Esto incluye la configuración de los parámetros
[YourCompanyCode],[StartDate]y[EndDate]. También debe reemplazar los IDs de tarea de workflow de los marcadores de posición ([Workflow Submitted Task ID],[Workflow Rejected Task ID],[Workflow Approved Task ID]) con los valores que identificó en el paso anterior. - Ejecutar la Consulta de Extracción: Ejecute la consulta SQL modificada contra la base de datos de SAP S/4HANA. Dependiendo del rango de fechas y el volumen de datos, la consulta puede tardar una cantidad significativa de tiempo en completarse. Se recomienda ejecutarla durante horas de menor actividad.
- Revisar los Resultados Iniciales: Una vez que la consulta finalice, examine las primeras filas de la salida para asegurarse de que todas las columnas, como JournalEntryId, ActivityName y EventTime, estén pobladas como se espera. El conjunto de resultados debe contener una fila para cada evento de negocio distinto en el ciclo de vida del asiento contable.
- Exportar Datos a CSV: Exporte todo el conjunto de resultados de su herramienta SQL a un único archivo CSV. Asegúrese de que el archivo utilice codificación UTF-8 para evitar problemas con caracteres especiales.
- Preparar para la Carga: Antes de cargar a una herramienta de process mining, confirme que el archivo CSV tiene las cabeceras requeridas. Los datos ya están estructurados como un registro de eventos, por lo que no debería ser necesaria ninguna transformación o pivote adicional.
Configuración
- Vistas de Core Data Services (CDS): La extracción utiliza principalmente
I_JournalEntrypara datos de cabecera eI_JournalEntryItempara detalles de partida individual e importe. Estas vistas proporcionan una interfaz simplificada y semánticamente rica para el diario universal (ACDOCA). - Tablas de Soporte: Para capturar una vista completa del proceso, la consulta también une varias tablas estándar de SAP:
CDHDRyCDPOSpara el seguimiento de cambios en documentos.SRGBRELySOODpara identificar cuándo se vinculan anexos a través de Servicios de Objetos Genéricos (GOS).SWW_WI2OBJySWWLOGHISTpara extraer eventos clave del workflow de aprobación.
- Filtrado por Rango de Fechas: Es crítico filtrar los datos por un rango de fechas específico para gestionar el rendimiento. Utilice el campo
I_JournalEntry.CreationDateTimeen la cláusulaWHERE. Se recomienda un rango de 3 a 6 meses para un análisis inicial. - Filtrado Organizacional: Siempre filtre por
CompanyCodepara limitar la extracción a las entidades legales relevantes. Consultar para todas las sociedades a la vez en un sistema grande puede resultar en tiempos de ejecución extremadamente largos. - IDs de Tarea de Workflow: La consulta contiene marcadores de posición para IDs de tarea de workflow (ej.,
[Workflow Approved Task ID]). Estos son únicos para cada instalación de SAP y deben configurarse correctamente para que las actividades de workflow sean extraídas. Sin ellos, no se capturarán eventos de envío, aprobación o rechazo. - Requisitos Previos: El usuario que ejecuta requiere amplias autorizaciones de lectura para tablas financieras, de sistema y de workflow. Estos permisos no son estándar y deben asignarse específicamente.
a Consulta de ejemplo sql
WITH JournalEntryAmountCTE AS (
SELECT
CompanyCode,
AccountingDocument,
FiscalYear,
SUM(AmountInCompanyCodeCurrency) AS AmountInLocalCurrency
FROM I_JournalEntryItem
GROUP BY CompanyCode, AccountingDocument, FiscalYear
),
JournalEntryBaseCTE AS (
SELECT
JE.CompanyCode,
JE.AccountingDocument,
JE.FiscalYear,
JE.CreatedByUser,
JE.CreationDateTime,
JE.PostingDateTime,
JE.PostingDate,
JE.AccountingDocumentType,
JE.DocumentIsParked,
JE.ReversedJournalEntry,
JE.TransactionCode,
JEA.AmountInLocalCurrency
FROM I_JournalEntry AS JE
LEFT JOIN JournalEntryAmountCTE AS JEA
ON JE.CompanyCode = JEA.CompanyCode
AND JE.AccountingDocument = JEA.AccountingDocument
AND JE.FiscalYear = JEA.FiscalYear
WHERE JE.CompanyCode IN ('[YourCompanyCode]')
AND JE.CreationDateTime BETWEEN '[StartDate]' AND '[EndDate]'
)
-- 1. Journal Entry Created
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Created' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
UNION ALL
-- 2. Journal Entry Parked
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Parked' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 3. Supporting Documentation Attached
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Supporting Documentation Attached' AS "ActivityName",
TO_TIMESTAMP(SOOD.CREDAT || ' ' || SOOD.CRETIM, 'YYYYMMDD HH24MISS') AS "EventTime",
SOOD.OWNER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SRGBREL ON SRGBREL.INSTID_A = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND SRGBREL.TYPEID_A = 'BKPF'
AND SRGBREL.CATID_A = 'BO'
JOIN SOOD ON SOOD.OBJTP = SRGBREL.TYPEID_B
AND SOOD.OBJYR = SRGBREL.INSTID_B(3)
AND SOOD.OBJNO = SRGBREL.INSTID_B(5)
UNION ALL
-- 4. Journal Submitted For Review
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Submitted For Review' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Submitted Task ID]'
UNION ALL
-- 5. Journal Entry Rejected
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Rejected' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Rejected Task ID]'
UNION ALL
-- 6. Journal Entry Corrected (changed while parked)
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Corrected' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 7. Journal Entry Approved
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Approved' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Approved Task ID]'
UNION ALL
-- 8. Manual Posting Identified
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Manual Posting Identified' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL AND BJE.TransactionCode IN ('FB01', 'F-02', 'FB50', 'FV50', 'FBB1', 'FBV1')
UNION ALL
-- 9. Journal Entry Posted
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Posted' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL
UNION ALL
-- 10. Journal Entry Changed After Posting
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Changed After Posting' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.PostingDateTime IS NOT NULL AND TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') > BJE.PostingDateTime
UNION ALL
-- 11. Journal Entry Cleared
SELECT
JEI.AccountingDocument AS "JournalEntryId",
'Journal Entry Cleared' AS "ActivityName",
MIN(JEI.ClearingDateTime) AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser", -- Note: Clearing user is not directly available here
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM I_JournalEntryItem AS JEI
JOIN JournalEntryBaseCTE AS BJE ON JEI.AccountingDocument = BJE.AccountingDocument
AND JEI.CompanyCode = BJE.CompanyCode
AND JEI.FiscalYear = BJE.FiscalYear
WHERE JEI.ClearingDateTime IS NOT NULL
GROUP BY JEI.AccountingDocument, BJE.CreatedByUser, BJE.CompanyCode, BJE.AccountingDocumentType, BJE.PostingDate, BJE.AmountInLocalCurrency
UNION ALL
-- 12. Journal Entry Reversal Processed
SELECT
OriginalDoc.AccountingDocument AS "JournalEntryId",
'Journal Entry Reversal Processed' AS "ActivityName",
ReversalDoc.PostingDateTime AS "EventTime",
ReversalDoc.CreatedByUser AS "CreatedByUser",
OriginalDoc.CompanyCode AS "CompanyCode",
OriginalDoc.AccountingDocumentType AS "JournalEntryType",
OriginalDoc.PostingDate AS "PostingDate",
OriginalDoc.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS ReversalDoc
JOIN JournalEntryBaseCTE AS OriginalDoc
ON ReversalDoc.ReversedJournalEntry = OriginalDoc.AccountingDocument
AND ReversalDoc.CompanyCode = OriginalDoc.CompanyCode
AND ReversalDoc.ReversalFiscalYear = OriginalDoc.FiscalYear
WHERE ReversalDoc.ReversedJournalEntry IS NOT NULL; Pasos
- Requisitos Previos y Acceso: Asegúrese de tener un usuario con las autorizaciones necesarias para consultar la base de datos subyacente de SAP S/4HANA o ejecutar informes ABAP. Necesitará acceso de lectura a las vistas CDS I_JournalEntry, I_JournalEntryItem, y a las tablas CDHDR, CDPOS, SRGBREL, SOOD, SWW_WI2OBJ y SWWLOGHIST. El acceso se concede típicamente a través de un cliente de base de datos como SAP HANA Studio, DBeaver, o utilizando las Herramientas de Desarrollo ABAP (ADT) de SAP para Eclipse.
- Identificar Configuraciones Específicas del Sistema: Antes de ejecutar la consulta, debe identificar los códigos de tarea específicos utilizados en su workflow de aprobación de asientos contables. Consulte con su administrador de workflow de SAP para encontrar los IDs de tarea (ej., TS12345678) que corresponden a eventos de envío, rechazo y aprobación. Estos son necesarios para los marcadores de posición en la consulta final.
- Preparar la Consulta SQL: Copie la consulta SQL completa proporcionada en la sección
queryen su cliente SQL o herramienta de desarrollo elegido. - Establecer Parámetros de Consulta: Localice los marcadores de posición dentro de la consulta y reemplácelos con sus valores específicos. Esto incluye la configuración de los parámetros
[YourCompanyCode],[StartDate]y[EndDate]. También debe reemplazar los IDs de tarea de workflow de los marcadores de posición ([Workflow Submitted Task ID],[Workflow Rejected Task ID],[Workflow Approved Task ID]) con los valores que identificó en el paso anterior. - Ejecutar la Consulta de Extracción: Ejecute la consulta SQL modificada contra la base de datos de SAP S/4HANA. Dependiendo del rango de fechas y el volumen de datos, la consulta puede tardar una cantidad significativa de tiempo en completarse. Se recomienda ejecutarla durante horas de menor actividad.
- Revisar los Resultados Iniciales: Una vez que la consulta finalice, examine las primeras filas de la salida para asegurarse de que todas las columnas, como JournalEntryId, ActivityName y EventTime, estén pobladas como se espera. El conjunto de resultados debe contener una fila para cada evento de negocio distinto en el ciclo de vida del asiento contable.
- Exportar Datos a CSV: Exporte todo el conjunto de resultados de su herramienta SQL a un único archivo CSV. Asegúrese de que el archivo utilice codificación UTF-8 para evitar problemas con caracteres especiales.
- Preparar para la Carga: Antes de cargar a una herramienta de process mining, confirme que el archivo CSV tiene las cabeceras requeridas. Los datos ya están estructurados como un registro de eventos, por lo que no debería ser necesaria ninguna transformación o pivote adicional.
Configuración
- Vistas de Core Data Services (CDS): La extracción utiliza principalmente
I_JournalEntrypara datos de cabecera eI_JournalEntryItempara detalles de partida individual e importe. Estas vistas proporcionan una interfaz simplificada y semánticamente rica para el diario universal (ACDOCA). - Tablas de Soporte: Para capturar una vista completa del proceso, la consulta también une varias tablas estándar de SAP:
CDHDRyCDPOSpara el seguimiento de cambios en documentos.SRGBRELySOODpara identificar cuándo se vinculan anexos a través de Servicios de Objetos Genéricos (GOS).SWW_WI2OBJySWWLOGHISTpara extraer eventos clave del workflow de aprobación.
- Filtrado por Rango de Fechas: Es crítico filtrar los datos por un rango de fechas específico para gestionar el rendimiento. Utilice el campo
I_JournalEntry.CreationDateTimeen la cláusulaWHERE. Se recomienda un rango de 3 a 6 meses para un análisis inicial. - Filtrado Organizacional: Siempre filtre por
CompanyCodepara limitar la extracción a las entidades legales relevantes. Consultar para todas las sociedades a la vez en un sistema grande puede resultar en tiempos de ejecución extremadamente largos. - IDs de Tarea de Workflow: La consulta contiene marcadores de posición para IDs de tarea de workflow (ej.,
[Workflow Approved Task ID]). Estos son únicos para cada instalación de SAP y deben configurarse correctamente para que las actividades de workflow sean extraídas. Sin ellos, no se capturarán eventos de envío, aprobación o rechazo. - Requisitos Previos: El usuario que ejecuta requiere amplias autorizaciones de lectura para tablas financieras, de sistema y de workflow. Estos permisos no son estándar y deben asignarse específicamente.
a Consulta de ejemplo sql
WITH JournalEntryAmountCTE AS (
SELECT
CompanyCode,
AccountingDocument,
FiscalYear,
SUM(AmountInCompanyCodeCurrency) AS AmountInLocalCurrency
FROM I_JournalEntryItem
GROUP BY CompanyCode, AccountingDocument, FiscalYear
),
JournalEntryBaseCTE AS (
SELECT
JE.CompanyCode,
JE.AccountingDocument,
JE.FiscalYear,
JE.CreatedByUser,
JE.CreationDateTime,
JE.PostingDateTime,
JE.PostingDate,
JE.AccountingDocumentType,
JE.DocumentIsParked,
JE.ReversedJournalEntry,
JE.TransactionCode,
JEA.AmountInLocalCurrency
FROM I_JournalEntry AS JE
LEFT JOIN JournalEntryAmountCTE AS JEA
ON JE.CompanyCode = JEA.CompanyCode
AND JE.AccountingDocument = JEA.AccountingDocument
AND JE.FiscalYear = JEA.FiscalYear
WHERE JE.CompanyCode IN ('[YourCompanyCode]')
AND JE.CreationDateTime BETWEEN '[StartDate]' AND '[EndDate]'
)
-- 1. Journal Entry Created
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Created' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
UNION ALL
-- 2. Journal Entry Parked
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Parked' AS "ActivityName",
BJE.CreationDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 3. Supporting Documentation Attached
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Supporting Documentation Attached' AS "ActivityName",
TO_TIMESTAMP(SOOD.CREDAT || ' ' || SOOD.CRETIM, 'YYYYMMDD HH24MISS') AS "EventTime",
SOOD.OWNER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SRGBREL ON SRGBREL.INSTID_A = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND SRGBREL.TYPEID_A = 'BKPF'
AND SRGBREL.CATID_A = 'BO'
JOIN SOOD ON SOOD.OBJTP = SRGBREL.TYPEID_B
AND SOOD.OBJYR = SRGBREL.INSTID_B(3)
AND SOOD.OBJNO = SRGBREL.INSTID_B(5)
UNION ALL
-- 4. Journal Submitted For Review
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Submitted For Review' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Submitted Task ID]'
UNION ALL
-- 5. Journal Entry Rejected
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Rejected' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Rejected Task ID]'
UNION ALL
-- 6. Journal Entry Corrected (changed while parked)
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Corrected' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.DocumentIsParked = 'X'
UNION ALL
-- 7. Journal Entry Approved
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Approved' AS "ActivityName",
LOG.END_TS AS "EventTime",
LOG.EXEC_USER AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN SWW_WI2OBJ AS WF_LINK ON WF_LINK.INSTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND WF_LINK.TYPEID = 'BKPF'
JOIN SWWLOGHIST AS LOG ON LOG.WI_ID = WF_LINK.WI_ID
WHERE LOG.METHOD = '[Workflow Approved Task ID]'
UNION ALL
-- 8. Manual Posting Identified
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Manual Posting Identified' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL AND BJE.TransactionCode IN ('FB01', 'F-02', 'FB50', 'FV50', 'FBB1', 'FBV1')
UNION ALL
-- 9. Journal Entry Posted
SELECT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Posted' AS "ActivityName",
BJE.PostingDateTime AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
WHERE BJE.PostingDateTime IS NOT NULL
UNION ALL
-- 10. Journal Entry Changed After Posting
SELECT DISTINCT
BJE.AccountingDocument AS "JournalEntryId",
'Journal Entry Changed After Posting' AS "ActivityName",
TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') AS "EventTime",
CH.USERNAME AS "CreatedByUser",
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS BJE
JOIN CDHDR AS CH ON CH.OBJECTID = CONCAT(BJE.CompanyCode, BJE.AccountingDocument, BJE.FiscalYear)
AND CH.OBJECTCLASS = 'BELEG'
WHERE BJE.PostingDateTime IS NOT NULL AND TO_TIMESTAMP(CH.UDATE || ' ' || CH.UTIME, 'YYYYMMDD HH24MISS') > BJE.PostingDateTime
UNION ALL
-- 11. Journal Entry Cleared
SELECT
JEI.AccountingDocument AS "JournalEntryId",
'Journal Entry Cleared' AS "ActivityName",
MIN(JEI.ClearingDateTime) AS "EventTime",
BJE.CreatedByUser AS "CreatedByUser", -- Note: Clearing user is not directly available here
BJE.CompanyCode AS "CompanyCode",
BJE.AccountingDocumentType AS "JournalEntryType",
BJE.PostingDate AS "PostingDate",
BJE.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM I_JournalEntryItem AS JEI
JOIN JournalEntryBaseCTE AS BJE ON JEI.AccountingDocument = BJE.AccountingDocument
AND JEI.CompanyCode = BJE.CompanyCode
AND JEI.FiscalYear = BJE.FiscalYear
WHERE JEI.ClearingDateTime IS NOT NULL
GROUP BY JEI.AccountingDocument, BJE.CreatedByUser, BJE.CompanyCode, BJE.AccountingDocumentType, BJE.PostingDate, BJE.AmountInLocalCurrency
UNION ALL
-- 12. Journal Entry Reversal Processed
SELECT
OriginalDoc.AccountingDocument AS "JournalEntryId",
'Journal Entry Reversal Processed' AS "ActivityName",
ReversalDoc.PostingDateTime AS "EventTime",
ReversalDoc.CreatedByUser AS "CreatedByUser",
OriginalDoc.CompanyCode AS "CompanyCode",
OriginalDoc.AccountingDocumentType AS "JournalEntryType",
OriginalDoc.PostingDate AS "PostingDate",
OriginalDoc.AmountInLocalCurrency AS "AmountInLocalCurrency"
FROM JournalEntryBaseCTE AS ReversalDoc
JOIN JournalEntryBaseCTE AS OriginalDoc
ON ReversalDoc.ReversedJournalEntry = OriginalDoc.AccountingDocument
AND ReversalDoc.CompanyCode = OriginalDoc.CompanyCode
AND ReversalDoc.ReversalFiscalYear = OriginalDoc.FiscalYear
WHERE ReversalDoc.ReversedJournalEntry IS NOT NULL; Pasos
- Crear el Programa ABAP: Acceda al Editor ABAP utilizando el código de transacción
SE38. Ingrese un nombre para el nuevo programa, por ejemplo,Z_PM_JE_EXTRACT, y haga clic en 'Crear'. Proporcione un título adecuado, establezca el 'Tipo' en 'Programa Ejecutable' y guárdelo como un objeto local o dentro de un paquete. - Definir la Pantalla de Selección: En el programa, defina parámetros y select-options que permitirán a los usuarios filtrar los datos. Esto debe incluir un rango de fechas para la fecha de creación del asiento contable (
P_CPUDT_FR,P_CPUDT_TO), un select-option para la Sociedad (SO_BUKRS) y una ruta de archivo para la salida en el servidor de aplicaciones (P_FPATH). - Declarar Estructuras de Datos: Defina una estructura de tabla interna que coincida con el formato de registro de eventos requerido. Esta estructura contendrá la salida final. Además, declare tablas internas y áreas de trabajo para las tablas SAP de las que seleccionará, como BKPF, ACDOCA, CDHDR, CDPOS y varias tablas de workflow.
- Implementar Lógica de Selección de Datos: Escriba la lógica ABAP central para recuperar datos para cada una de las 12 actividades requeridas. Cree subrutinas separadas (FORMs) para cada actividad para mantener el código organizado. Por ejemplo, cree una FORM para
get_created_events,get_parked_events,get_workflow_events, etc. - Seleccionar Eventos 'Creados' y 'Contabilizados': Lea de la tabla BKPF basándose en los criterios de la pantalla de selección del usuario. Una entrada en BKPF significa la creación. Un documento con estado
BSTAT = ' 'se considera contabilizado. Utilice la fecha/hora de creación (CPUDT,CPUTM) como tiempo del evento. - Seleccionar Eventos 'Aparcados': Lea de la tabla VBKPF, que almacena cabeceras de documentos aparcados. La fecha/hora de creación en esta tabla representa el evento de aparcamiento.
- Seleccionar Eventos de 'Workflow' (Enviado, Aprobado, Rechazado): Consulte tablas de workflow como SWW_WI2OBJ (para vincular un objeto de asiento contable a una instancia de workflow) y SWWLOGHIST o SWWIHEAD (para obtener los detalles y el momento de los pasos específicos). Deberá identificar los IDs de tarea de workflow específicos para el envío, la aprobación y el rechazo en su sistema.
- Seleccionar Eventos de 'Cambio' y 'Corrección': Consulte las tablas de documentos de cambio CDHDR (cabecera) y CDPOS (partida) para
OBJECTCLAS = 'BELEG'. Para 'Modificado Después de la Contabilización', filtre los cambios donde la fecha/hora de cambio sea posterior a la fecha de contabilización del documento. Para 'Corregido', filtre los cambios en documentos aparcados o rechazados. - Seleccionar Eventos de 'Anulación' y 'Compensación': Identifique las anulaciones buscando documentos donde el campo
STBLG(Nº documento de anulación) en BKPF esté relleno. El tiempo del evento de anulación es el tiempo de creación del documento de anulación. Identifique los eventos de compensación seleccionando la última fecha de compensación (AUGDT) de la tabla ACDOCA para las partidas individuales de un asiento contable dado. - Combinar y Ordenar Datos: A medida que se seleccionan los datos de cada actividad, añada los resultados a la tabla interna maestra final. Una vez completadas todas las selecciones, ordene la tabla maestra por
JournalEntryIdyEventTimepara asegurar el orden cronológico para cada caso. - Generar el Archivo de Salida: Utilice las sentencias
OPEN DATASET,LOOP AT... TRANSFERyCLOSE DATASETpara escribir el contenido de la tabla interna final ordenada en la ruta de archivo especificada en el servidor de aplicaciones SAP. El archivo debe estar en formato CSV con una fila de cabecera. - Programar Ejecución: Para extracciones regulares, utilice el código de transacción
SM36para crear un job de fondo que ejecute el programaZ_PM_JE_EXTRACTen un horario definido, por ejemplo, semanal o mensualmente. Esto automatiza el proceso de exportación de datos.
Configuración
- Rango de Fechas: La pantalla de selección debe tener un rango de fechas obligatorio para la fecha de creación del asiento contable (
CPUDT). Se recomienda extraer datos en bloques manejables, como de 3 a 6 meses a la vez, para asegurar un buen rendimiento. - Sociedad (
BUKRS): Este es un filtro crítico para limitar la extracción a las entidades legales específicas relevantes para el análisis de process mining. No se recomienda extraer para todas las sociedades a la vez. - Tipo de Documento (
BLART): Puede añadir este filtro opcional para enfocarse en tipos específicos de asientos contables, como 'SA' para Contabilización de Cuenta de Mayor o 'KR' para Facturas de Proveedores. Esto puede ayudar a reducir el volumen de datos y aumentar la relevancia del conjunto de datos. - Ruta del Archivo: El programa requiere una ruta de archivo lógica en el servidor de aplicaciones SAP donde se escribirá el archivo de salida. Asegúrese de que la ruta sea válida y que el usuario del sistema SAP tenga las autorizaciones de escritura necesarias para ese directorio. Utilice la transacción
AL11para gestionar y ver directorios del servidor. - IDs de Tarea de Workflow: La lógica para la extracción de eventos de workflow (Enviado, Aprobado, Rechazado) debe configurarse con los IDs de tarea específicos utilizados en el workflow de aprobación de asientos contables de su organización. Estos suelen ser personalizados y deben ser identificados por un consultor o desarrollador de workflow.
- Requisitos Previos: La cuenta de usuario o de sistema que ejecuta el programa requiere autorizaciones de desarrollador para crear y ejecutar programas ABAP (
S_DEVELOP) y un amplio acceso de lectura a tablas financieras (BKPF, ACDOCA), tablas de registro de cambios (CDHDR, CDPOS) y tablas de workflow (SWW*).
a Consulta de ejemplo abap
REPORT Z_PM_JE_EXTRACT.
*&---------------------------------------------------------------------*
*&-- Data Structures for Event Log --*
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
journalentryid TYPE string,
activityname TYPE string,
eventtime TYPE string,
createdbyuser TYPE uname,
companycode TYPE bukrs,
journalentrytype TYPE blart,
postingdate TYPE budat,
amountinlocalcurrency TYPE wrbtr,
END OF ty_event_log.
*&---------------------------------------------------------------------*
*&-- Selection Screen Definition --*
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
PARAMETERS: p_erdat_fr TYPE dats OBLIGATORY DEFAULT sy-datum-30,
p_erdat_to TYPE dats OBLIGATORY DEFAULT sy-datum.
SELECT-OPTIONS: so_bukrs FOR bkpf-bukrs OBLIGATORY.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/usr/sap/trans/tmp/je_event_log.csv'.
SELECTION-SCREEN END OF BLOCK b1.
*&---------------------------------------------------------------------*
*&-- Internal Tables --*
*&---------------------------------------------------------------------*
DATA: gt_event_log TYPE TABLE OF ty_event_log.
*&---------------------------------------------------------------------*
*&-- Main Processing Block --*
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_created_posted_events.
PERFORM get_parked_events.
PERFORM get_attachment_events.
PERFORM get_workflow_events.
PERFORM get_change_events.
PERFORM get_cleared_events.
PERFORM get_reversal_events.
SORT gt_event_log BY journalentryid eventtime.
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*&-- Subroutines for Extracting Individual Activities --*
*&---------------------------------------------------------------------*
FORM get_created_posted_events.
DATA: lt_bkpf TYPE TABLE OF bkpf,
ls_event_log TYPE ty_event_log,
lv_timestamp TYPE string.
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to.
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
CLEAR ls_event_log.
CONCATENATE <fs_bkpf>-bukrs <fs_bkpf>-belnr <fs_bkpf>-gjahr INTO ls_event_log-journalentryid.
ls_event_log-companycode = <fs_bkpf>-bukrs.
ls_event_log-journalentrytype = <fs_bkpf>-blart.
ls_event_log-postingdate = <fs_bkpf>-budat.
ls_event_log-createdbyuser = <fs_bkpf>-usnam.
" Timestamp format YYYY-MM-DDTHH:MI:SS
CONCATENATE <fs_bkpf>-cpudt(4) '-' <fs_bkpf>-cpudt+4(2) '-' <fs_bkpf>-cpudt+6(2) 'T' <fs_bkpf>-cputm(2) ':' <fs_bkpf>-cputm+2(2) ':' <fs_bkpf>-cputm+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
" Activity: Journal Entry Created
ls_event_log-activityname = 'Journal Entry Created'.
SELECT SUM( hsl ) INTO ls_event_log-amountinlocalcurrency FROM acdoca WHERE belnr = <fs_bkpf>-belnr AND gjahr = <fs_bkpf>-gjahr AND bukrs = <fs_bkpf>-bukrs.
APPEND ls_event_log TO gt_event_log.
" Activity: Journal Entry Posted (if not parked)
IF <fs_bkpf>-bstat = ' '.
ls_event_log-activityname = 'Journal Entry Posted'.
APPEND ls_event_log TO gt_event_log.
" Activity: Manual Posting Identified (based on T-Code)
CASE <fs_bkpf>-tcode.
WHEN 'FB01' OR 'F-02' OR 'FB50' OR 'F-22' OR 'F-43'.
ls_event_log-activityname = 'Manual Posting Identified'.
APPEND ls_event_log TO gt_event_log.
ENDCASE.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_parked_events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM vbkpf
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to.
CLEAR ls_event_log.
CONCATENATE vbkpf-bukrs vbkpf-belnr vbkpf-gjahr INTO ls_event_log-journalentryid.
CONCATENATE vbkpf-cpudt(4) '-' vbkpf-cpudt+4(2) '-' vbkpf-cpudt+6(2) 'T' vbkpf-cputm(2) ':' vbkpf-cputm+2(2) ':' vbkpf-cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Journal Entry Parked'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = vbkpf-usnam.
ls_event_log-companycode = vbkpf-bukrs.
ls_event_log-journalentrytype = vbkpf-blart.
ls_event_log-postingdate = vbkpf-budat.
APPEND ls_event_log TO gt_event_log.
ENDSELECT.
ENDFORM.
FORM get_attachment_events.
DATA: lt_bdocs TYPE TABLE OF srgbtbrel, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM srgbtbrel INTO TABLE lt_bdocs
WHERE typeid_a = 'BUS2081' " Object type for Accounting Document
AND catid_a = 'BO'.
LOOP AT lt_bdocs ASSIGNING FIELD-SYMBOL(<fs_bdocs>).
CHECK <fs_bdocs>-instid_a(4) IN so_bukrs.
DATA(lv_bukrs) = <fs_bdocs>-instid_a(4).
DATA(lv_belnr) = <fs_bdocs>-instid_a+4(10).
DATA(lv_gjahr) = <fs_bdocs>-instid_a+14(4).
SELECT SINGLE cpudt, cputm, usnam, blart, budat FROM bkpf
INTO (DATA(lv_cpudt), DATA(lv_cputm), DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = lv_bukrs AND belnr = lv_belnr AND gjahr = lv_gjahr.
IF sy-subrc = 0 AND lv_cpudt BETWEEN p_erdat_fr AND p_erdat_to.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
" Note: Using document creation time as a proxy for attachment time.
CONCATENATE lv_cpudt(4) '-' lv_cpudt+4(2) '-' lv_cpudt+6(2) 'T' lv_cputm(2) ':' lv_cputm+2(2) ':' lv_cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Supporting Documentation Attached'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = lv_bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_workflow_events.
" This is a simplified example. Real workflow logic can be complex.
" You must identify your specific Task IDs for these events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
DATA: BEGIN OF ls_wi, wi_id TYPE sww_wiid, cr_date TYPE sww_cd, cr_time TYPE sww_ct, task TYPE sww_task, instid TYPE swo_typeid, END OF ls_wi.
SELECT h~wi_id h~cr_date h~cr_time h~wi_rh_task o~instid
FROM swwwihead AS h
JOIN sww_wi2obj AS o ON h~wi_id = o~wi_id
INTO @ls_wi
WHERE o~typeid = 'BUS2081' AND o~catid = 'BO'
AND h~cr_date BETWEEN @p_erdat_fr AND @p_erdat_to.
DATA(lv_bukrs) = ls_wi-instid(4).
DATA(lv_belnr) = ls_wi-instid+4(10).
DATA(lv_gjahr) = ls_wi-instid+14(4).
IF lv_bukrs IN so_bukrs.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
CONCATENATE ls_wi-cr_date(4) '-' ls_wi-cr_date+4(2) '-' ls_wi-cr_date+6(2) 'T' ls_wi-cr_time(2) ':' ls_wi-cr_time+2(2) ':' ls_wi-cr_time+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-companycode = lv_bukrs.
CASE ls_wi-task.
WHEN '[Your Submit Task ID]'. " e.g., TS20000139
ls_event_log-activityname = 'Journal Submitted For Review'.
APPEND ls_event_log TO gt_event_log.
WHEN '[Your Approve Task ID]'. " e.g., TS20000142
ls_event_log-activityname = 'Journal Entry Approved'.
APPEND ls_event_log TO gt_event_log.
WHEN '[Your Reject Task ID]'. " e.g., TS20000141
ls_event_log-activityname = 'Journal Entry Rejected'.
APPEND ls_event_log TO gt_event_log.
ENDCASE.
ENDIF.
ENDSELECT.
ENDFORM.
FORM get_change_events.
DATA: lt_cdhdr TYPE TABLE OF cdhdr, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr
WHERE objectclas = 'BELEG'
AND udate BETWEEN p_erdat_fr AND p_erdat_to.
LOOP AT lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>).
DATA(lv_bukrs) = <fs_cdhdr>-objectid(4).
DATA(lv_belnr) = <fs_cdhdr>-objectid+4(10).
DATA(lv_gjahr) = <fs_cdhdr>-objectid+14(4).
IF lv_bukrs IN so_bukrs.
SELECT SINGLE bstat, budat, blart FROM bkpf
INTO (DATA(lv_bstat), DATA(lv_budat), DATA(lv_blart))
WHERE bukrs = lv_bukrs AND belnr = lv_belnr AND gjahr = lv_gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE lv_bukrs lv_belnr lv_gjahr INTO ls_event_log-journalentryid.
CONCATENATE <fs_cdhdr>-udate(4) '-' <fs_cdhdr>-udate+4(2) '-' <fs_cdhdr>-udate+6(2) 'T' <fs_cdhdr>-utime(2) ':' <fs_cdhdr>-utime+2(2) ':' <fs_cdhdr>-utime+4(2) INTO lv_timestamp.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = <fs_cdhdr>-username.
ls_event_log-companycode = lv_bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
IF lv_bstat = ' ' AND <fs_cdhdr>-udate > lv_budat.
ls_event_log-activityname = 'Journal Entry Changed After Posting'.
APPEND ls_event_log TO gt_event_log.
ELSEIF lv_bstat <> ' '.
ls_event_log-activityname = 'Journal Entry Corrected'.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_cleared_events.
DATA: ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
DATA: BEGIN OF ls_clear, belnr TYPE belnr_d, gjahr TYPE gjahr, bukrs TYPE bukrs, augdt TYPE augdt, END OF ls_clear, lt_clear LIKE TABLE OF ls_clear.
SELECT belnr, gjahr, bukrs, MAX( augdt ) AS augdt FROM acdoca
INTO TABLE @lt_clear
WHERE bukrs IN @so_bukrs
AND augdt NE '00000000'
AND augdt BETWEEN @p_erdat_fr AND @p_erdat_to
GROUP BY belnr, gjahr, bukrs.
LOOP AT lt_clear INTO ls_clear.
SELECT SINGLE usnam, blart, budat FROM bkpf
INTO (DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = ls_clear-bukrs AND belnr = ls_clear-belnr AND gjahr = ls_clear-gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE ls_clear-bukrs ls_clear-belnr ls_clear-gjahr INTO ls_event_log-journalentryid.
CONCATENATE ls_clear-augdt(4) '-' ls_clear-augdt+4(2) '-' ls_clear-augdt+6(2) 'T12:00:00' INTO lv_timestamp. " Clearing date has no time, use midday
ls_event_log-activityname = 'Journal Entry Cleared'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = ls_clear-bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM get_reversal_events.
DATA: lt_reversals TYPE TABLE OF bkpf, ls_event_log TYPE ty_event_log, lv_timestamp TYPE string.
SELECT * FROM bkpf INTO TABLE lt_reversals
WHERE bukrs IN so_bukrs
AND cpudt BETWEEN p_erdat_fr AND p_erdat_to
AND stblg IS NOT NULL.
LOOP AT lt_reversals ASSIGNING FIELD-SYMBOL(<fs_rev>).
SELECT SINGLE usnam, blart, budat FROM bkpf
INTO (DATA(lv_usnam), DATA(lv_blart), DATA(lv_budat))
WHERE bukrs = <fs_rev>-bukrs AND belnr = <fs_rev>-stblg AND gjahr = <fs_rev>-gjahr.
IF sy-subrc = 0.
CLEAR ls_event_log.
CONCATENATE <fs_rev>-bukrs <fs_rev>-stblg <fs_rev>-gjahr INTO ls_event_log-journalentryid.
CONCATENATE <fs_rev>-cpudt(4) '-' <fs_rev>-cpudt+4(2) '-' <fs_rev>-cpudt+6(2) 'T' <fs_rev>-cputm(2) ':' <fs_rev>-cputm+2(2) ':' <fs_rev>-cputm+4(2) INTO lv_timestamp.
ls_event_log-activityname = 'Journal Entry Reversal Processed'.
ls_event_log-eventtime = lv_timestamp.
ls_event_log-createdbyuser = lv_usnam.
ls_event_log-companycode = <fs_rev>-bukrs.
ls_event_log-journalentrytype = lv_blart.
ls_event_log-postingdate = lv_budat.
APPEND ls_event_log TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
FORM write_output_file.
DATA: lv_line TYPE string.
FIELD-SYMBOLS: <fs_event_log> TYPE ty_event_log.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc NE 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_line = 'JournalEntryId,ActivityName,EventTime,CreatedByUser,CompanyCode,JournalEntryType,PostingDate,AmountInLocalCurrency'.
TRANSFER lv_line TO p_fpath.
LOOP AT gt_event_log ASSIGNING <fs_event_log>.
CONCATENATE <fs_event_log>-journalentryid <fs_event_log>-activityname <fs_event_log>-eventtime <fs_event_log>-createdbyuser <fs_event_log>-companycode <fs_event_log>-journalentrytype <fs_event_log>-postingdate <fs_event_log>-amountinlocalcurrency
INTO lv_line SEPARATED BY ','.
TRANSFER lv_line TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'File successfully written to', p_fpath.
ENDFORM.