Template de dados: Purchase to Pay - Pedido de Compra
Seu Template de dados de Purchase to Pay - Pedido de Compra
- Atributos recomendados para coletar
- Atividades-chave a monitorizar
- Orientações de extração do SAP ECC
Procure to Pay (P2P) - Atributos de Pedido de Compra
| Nome | Descrição | ||
|---|---|---|---|
Atividade Activity | Nome do evento de negócio ou da etapa que ocorreu no ciclo de vida do pedido de compra. | ||
Descrição Este atributo descreve uma etapa do processo, como 'Pedido de Compra criado', 'Pedido de Compra aprovado' ou 'Recebimento de mercadorias lançado'. A sequência dessas atividades forma o fluxo do processo para cada Pedido de Compra. Analisar a sequência, a frequência e o tempo entre as atividades é o coração do Process Mining. Isso ajuda a identificar gargalos, ciclos de retrabalho e desvios do processo padrão, permitindo melhorias direcionadas e esforços de padronização. Por que é importante As atividades definem as etapas do processo. Analisar a sequência e os tempos revela o fluxo real do processo, os gargalos e os desvios. Onde obter Derivado de várias tabelas e logs de transação do SAP, como CDHDR/CDPOS para alterações, EKBE para GR/IR e EBAN para requisições. Geralmente requer uma lógica ou um programa de extração customizado. Exemplos Pedido de Compra criadoPedido de Compra aprovadoEntrada de mercadorias lançada | |||
Pedido de Compra PurchaseOrder | Identificador único do documento de pedido de compra (PO), que atua como o caso principal para acompanhar o processo de compras. | ||
Descrição O número do pedido de compra é o identificador central que conecta todas as atividades, da criação ao recebimento de mercadorias e à conclusão. Cada PO com número único representa uma instância do processo de compras. Em Process Mining, esse atributo é essencial para reconstruir a jornada ponta a ponta de cada compra. Ele permite análises detalhadas de tempos de ciclo, variações de processo e verificações de conformidade para cada pedido, formando a base de todo o modelo do processo. Por que é importante Este é o identificador central que conecta todos os eventos relacionados, possibilitando analisar o ciclo de vida completo de cada pedido de compra. Onde obter Tabela: EKKO, Campo: EBELN Exemplos 450001762345000176244500017625 | |||
Tempo do Evento EventTime | A data e hora precisas em que a atividade ocorreu. | ||
Descrição Este timestamp marca o momento exato em que um evento ocorreu, como a hora em que um PO foi aprovado ou quando um recebimento de mercadorias foi lançado. Ele estabelece a ordem cronológica de todas as atividades dentro de um caso. Timestamps são fundamentais para Process Mining, pois viabilizam todas as análises baseadas em tempo. Isso inclui calcular tempos de ciclo entre atividades, identificar atrasos, analisar o throughput do processo e medir o desempenho frente a SLAs (acordos de nível de serviço). Por que é importante Este timestamp é fundamental para calcular todas as métricas baseadas em duração, como tempos de ciclo e gargalos, e para ordenar os eventos cronologicamente. Onde obter Derivado de vários campos de data e hora nas tabelas do SAP, como EKKO-AEDAT (Data de alteração), CDHDR-UDATE/UTIME (Timestamp do log de alterações) ou EKBE-BUDAT (Data de lançamento). Exemplos 2023-04-15T10:05:31Z2023-04-16T14:22:00Z2023-05-01T09:00:15Z | |||
Código da Empresa CompanyCode | Identificador da empresa ou entidade legal que iniciou a compra. | ||
Descrição O Código da Empresa (Company Code) representa uma entidade legal independente no SAP. Todas as transações são lançadas no nível do Company Code, tornando-o uma unidade organizacional fundamental. Analisar o processo por Company Code permite comparar a eficiência de compras e a conformidade entre diferentes unidades de negócio ou países. Ajuda a identificar boas práticas em uma entidade que podem ser replicadas em outras e a apontar unidades específicas que estão enfrentando dificuldades no processo. Por que é importante Representa a entidade jurídica, permitindo comparar o desempenho do processo e verificar a conformidade entre diferentes partes da organização. Onde obter Tabela: EKKO, Campo: BUKRS Exemplos 10002100US01 | |||
Grupo de materiais MaterialGroup | Uma classificação usada para agrupar materiais ou serviços com características semelhantes. | ||
Descrição O Grupo de Mercadorias (categoria de compra) classifica o tipo de bem ou serviço adquirido. Exemplos: 'Hardware de TI', 'Materiais de escritório' ou 'Serviços profissionais'. Esse atributo é vital para análise de gastos e entendimento dos padrões de compras. Permite filtrar o processo para ver como cada categoria é tratada, quem aprova e quais fornecedores a atendem. É uma dimensão-chave no dashboard 'Purchase Order Value Analysis'. Por que é importante Permite segmentar o processo por categoria de produto ou serviço, evidenciando comportamentos, tempos de ciclo e fornecedores diferentes conforme o tipo de gasto. Onde obter Tabela: EKPO, Campo: MATKL Exemplos 00101IT_HWCONSULT | |||
Nome do Utilizador UserName | ID do usuário da pessoa que executou a atividade. | ||
Descrição Este atributo captura o nome de usuário do SAP do colaborador que criou, alterou ou aprovou um documento. Em etapas automatizadas, pode exibir um usuário técnico (system/batch). Analisar por usuário ajuda a identificar necessidades de treinamento, pessoas de alto desempenho ou possíveis problemas de conformidade. É fundamental para montar dashboards de distribuição de carga de trabalho, conformidade com a matriz de aprovação e para entender o desempenho de equipes ou indivíduos. Por que é importante Atribui as ações dos usuários a pessoas específicas, permitindo analisar performance, carga de trabalho e aderência às regras de conformidade. Onde obter Tabela: EKKO, Campo: ERNAM (Criado por); Tabela: CDHDR, Campo: USERNAME (Alterado por). Exemplos JSMITHMBROWNBATCH_USER | |||
Número do fornecedor VendorNumber | Identificador único do fornecedor. | ||
Descrição É o código que identifica de forma única o fornecedor de quem os bens ou serviços estão sendo adquiridos. Trata-se de um dado mestre crítico no processo de compras. Esse atributo é essencial para análises centradas no fornecedor. Permite avaliar o desempenho de entregas, comparar lead times entre fornecedores e analisar padrões de gastos. É a dimensão primária do dashboard 'Desempenho de Entrega do Fornecedor'. Por que é importante Permite analisar a performance dos fornecedores, ajudando a identificar parceiros confiáveis e aqueles que causam atrasos ou problemas de qualidade. Onde obter Tabela: EKKO, Campo: LIFNR Exemplos 100345V-20598700112 | |||
Tipo de Documento DocumentType | Um código que classifica os diferentes tipos de pedidos de compra. | ||
Descrição O Tipo de Documento é uma configuração do SAP que controla a faixa de numeração, a seleção de campos e o fluxo do processo do pedido de compra. Por exemplo, podem existir tipos diferentes para POs padrão, POs de serviço ou ordens de transporte de estoque. Esse atributo é uma dimensão poderosa de análise, pois tipos de documento diferentes costumam seguir processos intencionalmente distintos. Filtrar por tipo de documento permite uma comparação equivalente de tempos de ciclo e fluxos do processo. Por que é importante Distingue diferentes tipos de processos de compra (ex.: padrão, serviço, devolução), que normalmente têm fluxos e metas de performance distintas. Onde obter Tabela: EKKO, Campo: BSART Exemplos NBFOUB | |||
Valor do Pedido OrderAmount | Valor monetário total do item do pedido de compra. | ||
Descrição Este atributo representa o valor total de um item específico do Pedido de Compra, calculado como quantidade multiplicada pelo preço líquido. Para obter o valor total do PO, é necessário agregar os itens. Analisar o processo pelo valor do pedido é crucial para identificar transações de alto valor que podem exigir controles mais rigorosos ou caminhos de aprovação diferentes. Ele alimenta o dashboard 'Análise de Valor de Pedidos de Compra' e ajuda a priorizar esforços de melhoria nos pedidos de maior impacto financeiro. Por que é importante Quantifica o impacto financeiro de cada compra, permitindo análises baseadas em valor para priorizar pedidos de alto impacto ou identificar oportunidades de redução de custos. Onde obter Tabela: EKPO, Campo: NETWR (Valor líquido do pedido). Exemplos 1500.00250.7512345.50 | |||
Centro Plant | Local físico ou planta onde os bens serão entregues. | ||
Descrição A Planta é uma unidade organizacional que representa uma instalação de produção, um armazém ou outro local onde bens ou serviços são recebidos. Analisar por Planta ajuda a entender variações geográficas no processo de compras. Pode revelar diferenças nos prazos de entrega dos fornecedores para determinados locais ou destacar plantas com processos de recebimento ineficientes, apoiando a análise da pontualidade no recebimento de mercadorias. Por que é importante Especifica o local de entrega, útil para analisar diferenças regionais do processo e o desempenho logístico. Onde obter Tabela: EKPO, Campo: WERKS Exemplos 100011002000 | |||
Data de entrega solicitada RequestedDeliveryDate | Data em que a empresa solicitou ao fornecedor a entrega dos bens ou serviços. | ||
Descrição É a data de entrega desejada informada no pedido de compra. Serve como referência para medir o desempenho real da entrega. Essa data é essencial para calcular o KPI 'Taxa de Recebimento no Prazo'. Ao comparar a data real de recebimento de mercadorias com a data solicitada, as organizações podem medir quantitativamente a confiabilidade do fornecedor e a eficiência do recebimento interno, dando suporte direto ao dashboard 'Desempenho de Entrega do Fornecedor'. Por que é importante É a data-alvo de entrega, essencial para calcular KPIs de desempenho no prazo e avaliar a confiabilidade do fornecedor. Onde obter Tabela: EKPO, Campo: EINDT Exemplos 2023-06-102023-07-222023-08-01 | |||
É uma alteração pós-aprovação IsPostApprovalChange | Indicador que mostra se houve alteração no Pedido de Compra após a aprovação inicial. | ||
Descrição Este atributo booleano é verdadeiro quando uma atividade 'Purchase Order Changed' é detectada após uma atividade 'Purchase Order Approved' para o mesmo PO. Ele ajuda a isolar alterações problemáticas que ocorrem tardiamente no processo. Esse campo calculado sustenta diretamente o KPI 'Taxa de Alterações Pós-Aprovação do PO' e o dashboard 'Retrabalho e Alterações em Pedidos de Compra'. Ajuda a quantificar e destacar alterações disruptivas que podem causar atrasos e exigir nova aprovação, apontando problemas na especificação ou no escopo inicial. Por que é importante Mede diretamente o retrabalho após a aprovação, um KPI-chave para a estabilidade e a eficiência do processo. Taxas altas indicam problemas na definição de requisitos a montante. Onde obter Este é um atributo calculado, derivado da sequência de atividades no Event Log. Exemplos verdadeirofalse | |||
Entrega Dentro do Prazo IsOnTimeDelivery | Indicador que mostra se as mercadorias foram recebidas na data de entrega solicitada ou antes. | ||
Descrição Este atributo booleano é verdadeiro se o timestamp da atividade 'Goods Receipt Posted' ocorrer na 'Data de Entrega Solicitada' ou antes dela. Ele fornece um resultado binário claro sobre o desempenho de entrega em cada item do PO. Esse atributo é a base do KPI 'Taxa de Recebimento no Prazo'. Ele simplifica a análise do desempenho do fornecedor e da eficiência interna de recebimento, facilitando a agregação e o filtro de entregas no prazo versus atrasadas. Por que é importante Fornece uma métrica clara de sucesso ou falha na pontualidade das entregas, apoiando diretamente KPIs e dashboards de performance de fornecedores. Onde obter Este é um atributo calculado, obtido pela comparação entre a data de lançamento do recebimento de mercadorias (EKBE-BUDAT) e a data de entrega solicitada (EKPO-EINDT). Exemplos verdadeirofalse | |||
Grupo de Compras PurchasingGroup | Comprador específico ou grupo de compradores responsável pela atividade de compras. | ||
Descrição O Grupo de Compradores representa a pessoa ou equipe responsável por determinada atividade de compras. É o principal ponto de contato com os fornecedores. Esse atributo oferece um nível de análise mais granular do que a Organização de Compras. Ajuda a entender a distribuição de trabalho entre compradores e a identificar diferenças de desempenho no nível do comprador, orientando a alocação de recursos e iniciativas de treinamento. Por que é importante Oferece uma visão detalhada de quem responde pela compra, permitindo análises de carga de trabalho e performance no nível do comprador ou do time. Onde obter Tabela: EKKO, Campo: EKGRP Exemplos 001002N01 | |||
Moeda Currency | Código da moeda do valor do pedido de compra. | ||
Descrição Este atributo indica a moeda na qual o valor do Pedido de Compra é expresso, como USD, EUR ou GBP. Ele fornece contexto essencial para quaisquer valores monetários. Para organizações globais, a moeda é fundamental para análises financeiras corretas. Ela permite a agregação e comparação adequadas dos valores dos pedidos, e todos os KPIs monetários devem ser interpretados no contexto de sua moeda. Por que é importante Fornece o contexto necessário para todos os valores monetários, garantindo análises financeiras precisas, especialmente em organizações multinacionais. Onde obter Tabela: EKKO, Campo: WAERS Exemplos USDEURJPY | |||
Motivo da Rejeição RejectionReason | Código ou texto do motivo explicando por que uma requisição de compra ou pedido foi rejeitado. | ||
Descrição Este atributo registra o motivo específico informado quando um Pedido de Compra é rejeitado durante o workflow de aprovação. Essa informação é crucial para entender as causas principais de retrabalho e atrasos. Analisar os motivos de rejeição ajuda a identificar problemas recorrentes, como precificação incorreta, estouro de orçamento ou seleção de fornecedores fora de conformidade. Esse insight permite atacar as causas principais, melhorar a qualidade na criação inicial do PO e agilizar o processo de aprovação. Por que é importante Traz visibilidade direta sobre por que aprovações falham, viabilizando melhorias específicas para reduzir retrabalho e encurtar o tempo de ciclo de aprovação. Onde obter Essas informações podem ser difíceis de localizar. Podem estar em campos de texto longo ou depender de configurações de workflow personalizadas. Frequentemente exigem conhecimento específico da implementação. Exemplos Preço incorretoOrçamento excedidoSolicitação duplicada | |||
Nome do Fornecedor VendorName | Razão social do fornecedor. | ||
Descrição Nome do fornecedor, mais intuitivo para o usuário do que o número do fornecedor. Normalmente vem do cadastro mestre de fornecedores. Enquanto o Número do Fornecedor é usado para joins e identificação única, o Nome do Fornecedor é essencial para dashboards e relatórios voltados ao usuário. Ele torna as análises mais intuitivas e acessíveis para quem não está familiarizado com os códigos do fornecedor. Por que é importante Exibe o nome do fornecedor de forma legível, tornando dashboards e relatórios muito mais fáceis de entender para usuários de negócio. Onde obter Tabela: LFA1, Campo: NAME1. Isso requer um join entre EKKO-LIFNR e LFA1-LIFNR. Exemplos Staples Inc.Global Tech SolutionsOffice Supply Co. | |||
Organização de Compras PurchasingOrganization | Unidade organizacional responsável por negociar preços e adquirir materiais ou serviços. | ||
Descrição A Organização de Compras é uma unidade organizacional-chave no SAP responsável pelas atividades de compras. Pode ser centralizada para toda a empresa ou descentralizada por planta ou região. Analisar o desempenho do processo por Organização de Compras ajuda a identificar quais equipes são mais eficientes. Permite comparar métricas como tempos de ciclo, taxas de retrabalho e custos entre unidades, evidenciando boas práticas e áreas que precisam de suporte. Por que é importante Identifica a equipe de compras responsável, permitindo comparar a performance e analisar diferentes unidades organizacionais. Onde obter Tabela: EKKO, Campo: EKORG Exemplos 1000US01DE01 | |||
Requisição de Compra PurchaseRequisition | Identificador da requisição de compra que antecedeu o pedido de compra. | ||
Descrição Este atributo vincula o Pedido de Compra à sua Requisição de Compra de origem. Nem todo PO terá uma requisição anterior. Esse vínculo é vital para analisar o dashboard 'Conversão de Requisição em Pedido' e o KPI 'Taxa de Conversão de PR para PO'. Ele permite medir a eficiência do processo nas etapas iniciais, do pedido inicial à criação do pedido formal, e identificar POs não conformes criados sem requisição. Por que é importante Vincula o Pedido de Compra à requisição de origem, permitindo analisar a conversão de PR para PO e identificar Pedidos de Compra criados sem requisição prévia. Onde obter Tabela: EKPO, Campo: BANFN Exemplos 1001589010015891 | |||
Sistema de Origem SourceSystem | O sistema do qual os dados foram extraídos. | ||
Descrição Este atributo identifica a origem dos dados, que normalmente é o identificador de uma instância SAP ECC (por exemplo, 'ECC_PROD_100'). Em ambientes com múltiplos sistemas, ajuda a diferenciar as fontes de dados. Para governança e linhagem de dados, conhecer o sistema de origem é crucial. Isso garante a integridade dos dados e ajuda na solução de problemas de extração ou qualidade, especialmente quando os dados são combinados de diferentes sistemas ERP ou módulos. Por que é importante Identifica a origem dos dados, essencial para governança, validação e gestão de análises entre diferentes sistemas. Onde obter Normalmente, é um valor estático adicionado durante a extração de dados para identificar o conjunto de dados com seu sistema de origem. Exemplos SAP_ECC_PRODECC_EU_100S4H_FIN | |||
Tempo de ciclo ponta a ponta EndToEndCycleTime | Tempo total decorrido da primeira à última atividade de um pedido de compra. | ||
Descrição Essa métrica mede a duração de todo o processo de pedido de compra, do evento mais antigo (por exemplo, 'Requisição de Compra Criada') ao evento final (por exemplo, 'Pedido de Compra Concluído'). É um KPI crítico para mensurar a eficiência geral do processo. Oferece uma visão geral do desempenho e ajuda a identificar os casos mais longos e os gargalos em geral. Dá suporte direto ao dashboard 'Análise do tempo de ciclo end-to-end de PO' e ao KPI 'Tempo de ciclo end-to-end médio de PO'. Por que é importante Mede a velocidade e a eficiência de todo o processo de compras, servindo como um indicador-chave da saúde do processo. Onde obter Este é um atributo calculado, determinado subtraindo, para cada caso, o timestamp do primeiro evento do timestamp do último evento. Exemplos 10 days 4 hours22 dias e 1 hora5 dias e 8 horas | |||
Última Atualização de Dados LastDataUpdate | Carimbo de data e hora que indica quando os dados foram atualizados pela última vez a partir do sistema de origem. | ||
Descrição Este atributo registra a data e a hora da extração ou atualização de dados mais recente. Ele dá contexto sobre a atualidade dos dados analisados. Exibir essa informação nos dashboards é vital para que os usuários entendam se os insights se baseiam em dados quase em tempo real ou em um instantâneo histórico. Isso alinha expectativas e garante decisões com base em dados de idade conhecida. Por que é importante Informa os usuários sobre quão atuais estão os dados, garantindo que entendam se a análise reflete o estado mais recente das operações. Onde obter Este timestamp é gerado e adicionado pelo processo de extração de dados ou ETL no momento da execução. Exemplos 2023-10-27T02:00:00Z2023-10-28T02:00:00Z | |||
Procure to Pay (P2P) - Atividades de Pedido de Compra
| Atividade | Descrição | ||
|---|---|---|---|
Entrada de mercadorias lançada | Esta atividade indica o recebimento físico de mercadorias de um fornecedor relativo a um Pedido de Compra específico. Lançar o recebimento de mercadorias é uma ação explícita (por exemplo, via transação MIGO) que cria um documento de material e atualiza o estoque. | ||
Por que é importante Este é um marco crítico para acompanhar o desempenho de entrega do fornecedor e o início do processo de conferência de faturas. É usado para calcular a taxa de entrega no prazo e a pontualidade do recebimento de mercadorias. Onde obter Registrado na criação de um documento de material. O timestamp do evento é a data de lançamento (MKPF-BUDAT) ou a data de criação (MKPF-CPUDT) do cabeçalho do documento de material (MKPF), vinculado ao Pedido de Compra pela tabela de itens (MSEG). Captura Use o timestamp de lançamento/criação da tabela MKPF para documentos de material que referenciam o PO. Tipo de evento explicit | |||
Pedido de Compra aprovado | Representa a aprovação final do pedido de compra, autorizando o envio ao fornecedor. Esse marco é normalmente inferido pela mudança do status de liberação do pedido para \"totalmente liberado\" ou \"aprovado\". | ||
Por que é importante Essa atividade é crítica para calcular o KPI de tempo de ciclo de aprovação do PO e identificar gargalos no workflow de aprovação. É pré-requisito para a maioria das atividades seguintes, como o envio do pedido ao fornecedor. Onde obter Inferido ao rastrear os logs de alteração (CDHDR/CDPOS) da tabela de cabeçalho do Pedido de Compra (EKKO) para identificar quando o código final de liberação é aplicado ou quando o indicador de status geral de liberação (EKKO-FRGKE) é definido como 'liberado'. Captura Identifique o timestamp em que o status geral de liberação do PO (EKKO-FRGKE) muda para o estado de aprovação final. Tipo de evento inferred | |||
Pedido de Compra concluído | Indica que um item do pedido de compra é considerado totalmente entregue. Trata-se de um evento inferido, normalmente derivado do indicador 'Entrega concluída' definido automática ou manualmente no item do pedido. | ||
Por que é importante Esta atividade marca o ponto final lógico da etapa de atendimento do Pedido de Compra no processo. Ela é essencial para calcular o tempo de ciclo do PO de ponta a ponta, da criação à conclusão. Onde obter Inferido a partir dos documentos de alteração (CDHDR/CDPOS) que registram quando o indicador 'Entrega concluída' (EKPO-ELIKZ) é definido como 'X' para um item do PO. O último item marcado como concluído pode sinalizar a conclusão do PO inteiro. Captura Identifique o timestamp nos documentos de alteração quando o indicador EKPO-ELIKZ for definido. Tipo de evento inferred | |||
Pedido de Compra criado | Esta atividade marca a criação de um Pedido de Compra formal, que é um contrato vinculante com o fornecedor. É um evento explícito, registrado quando um usuário cria e salva um PO (por exemplo, via transação ME21N), gerando registros nas tabelas EKKO e EKPO. | ||
Por que é importante Marca o início oficial do ciclo de vida do Pedido de Compra. Serve como marco para medir o tempo de conversão de PR para PO e o tempo de atendimento ponta a ponta do pedido. Onde obter Capturado a partir da data de criação (EKKO-AEDAT) na tabela de cabeçalho do Pedido de Compra (EKKO) para o número de pedido correspondente (EKKO-EBELN). Captura Use o timestamp de criação da tabela EKKO para cada novo Pedido de Compra. Tipo de evento explicit | |||
Pedido de Compra enviado ao fornecedor | Esta atividade marca o momento em que o pedido de compra aprovado é oficialmente enviado ao fornecedor, por exemplo, via EDI, e-mail ou impressão. É um evento explícito capturado nas tabelas de controle de mensagens quando uma mensagem de saída é processada com sucesso. | ||
Por que é importante Este é um marco crítico que inicia a contagem do lead time do fornecedor. Analisar o tempo entre este evento e o recebimento de mercadorias é essencial para avaliar o desempenho do fornecedor e a pontualidade das entregas. Onde obter Registrado na tabela de status de mensagem (NAST). O timestamp pode ser obtido de NAST-DATVR e NAST-UHRVR quando o status de processamento (NAST-VSTAT) for "1" (processado com sucesso) para o tipo de saída do pedido correspondente. Captura Use o timestamp de processamento da tabela NAST para a mensagem de saída do PO. Tipo de evento explicit | |||
Requisição de Compra Criada | Esta atividade marca a criação de uma solicitação formal de bens ou serviços. É um evento explícito capturado quando o usuário salva um novo documento de requisição de compra (usando transações como ME51N), o que gera um registro único na tabela EBAN. | ||
Por que é importante Este é o ponto de partida principal do processo de compras. Analisar o tempo entre este evento e a criação do pedido de compra ajuda a medir a eficiência na conversão da demanda interna em pedidos prontos para execução. Onde obter Registrado quando é criada uma entrada na tabela de cabeçalho da Requisição de Compra (EBAN). A data de criação (EBAN-BADAT) e a hora servem como timestamp para esse evento. Captura Identifique novas entradas na tabela EBAN com base na data de criação. Tipo de evento explicit | |||
Aprovação do Pedido de Compra solicitada | Indica que um pedido de compra criado ou alterado foi enviado para aprovação conforme a estratégia de liberação configurada. Esse evento é inferido quando a estratégia de liberação é disparada e o PO entra em status de aprovação pendente. | ||
Por que é importante Diferenciar a criação do Pedido de Compra do início da aprovação permite medir com precisão o KPI de tempo de aprovação. Também evidencia qualquer espera antes de o workflow de aprovação começar. Onde obter Inferido a partir dos documentos de alteração (CDHDR/CDPOS) do Pedido de Compra (objeto EINKBELEG) que mostram a definição inicial de um status de liberação, ou quando o status geral de liberação (EKKO-FRGKE) é definido pela primeira vez com um valor que indica que um processo de aprovação está ativo. Captura Identifique a primeira entrada de documento de alteração que dispara a estratégia de liberação do PO. Tipo de evento inferred | |||
Confirmação de Serviços Registrada | Para pedidos de compra de serviços, esta atividade representa a confirmação de que os serviços foram prestados. É um evento explícito capturado por meio da criação de uma Folha de Entrada de Serviços (FES), por exemplo, via transação ML81N. | ||
Por que é importante É o equivalente ao recebimento de mercadorias no caso de serviços e é essencial para acompanhar o cumprimento das ordens de serviço. Ele aciona o processo financeiro de pagamento do serviço. Onde obter Capturado a partir da data de criação (ESSR-ERDAT) na tabela de cabeçalho do Service Entry Sheet (ESSR). O vínculo com o pedido de compra está na tabela ESLL. Captura Use o timestamp de criação da tabela ESSR para as folhas de entrada de serviço (FES) vinculadas ao PO. Tipo de evento explicit | |||
Inspeção de Qualidade Realizada | Indica que as mercadorias recebidas passaram por inspeção de qualidade. Essa atividade é geralmente inferida quando um lote de inspeção, criado no momento do recebimento de mercadorias, recebe uma decisão de uso no módulo de Gestão da Qualidade (QM). | ||
Por que é importante Em setores em que a qualidade é crítica, esta atividade ajuda a analisar a duração e os resultados do processo de inspeção. Atrasos aqui podem criar gargalos entre o recebimento das mercadorias e a disponibilidade para uso. Onde obter Inferido a partir do módulo de Gestão da Qualidade. Um lote de inspeção é criado (tabela QALS) no recebimento de mercadorias, e a atividade é marcada pela criação de uma decisão de uso (tabela QAVE), que inclui um timestamp. Captura Identifique o timestamp da decisão de uso na tabela QAVE para o lote de inspeção vinculado ao documento de material. Tipo de evento inferred | |||
Mercadorias devolvidas | Representa a devolução ao fornecedor de mercadorias previamente recebidas, geralmente por problema de qualidade ou envio incorreto. É um evento explícito, registrado pelo lançamento de um documento de material com um tipo de movimento específico de devolução. | ||
Por que é importante Essa atividade evidencia problemas de qualidade do fornecedor ou de exatidão do pedido e é um indicador-chave de retrabalho no processo. É crucial para calcular o KPI de Taxa de Divergência no Recebimento de Mercadorias. Onde obter Registrado nas tabelas de documentos de material (MKPF/MSEG) quando é usado um tipo de movimento de devolução (por exemplo, '122' para Devolução ao Fornecedor). A data de lançamento (MKPF-BUDAT) serve como timestamp. Captura Identifique documentos de material com tipo de movimento de devolução (por ex., 122) que referenciem o PO original. Tipo de evento explicit | |||
Pedido de Compra alterado | Representa qualquer modificação feita em um pedido de compra após sua criação inicial, como mudanças de quantidade, preço ou datas de entrega. Essas alterações são registradas explicitamente no sistema de documentos de alteração do SAP. | ||
Por que é importante Muitas alterações, especialmente após a aprovação, indicam ineficiências de processo, planejamento inicial inadequado ou aumento de escopo. Esta atividade é fundamental para o dashboard de Retrabalho e Alterações de PO e para os KPIs relacionados. Onde obter Registradas explicitamente nas tabelas de cabeçalho (CDHDR) e item (CDPOS) de documentos de alteração do objeto Pedido de Compra (EINKBELEG). Cada alteração cria uma nova entrada com timestamp. Captura Extraia eventos de alteração e timestamps das tabelas CDHDR e CDPOS vinculadas ao número do Pedido de Compra. Tipo de evento explicit | |||
Pedido de Compra excluído | Representa o cancelamento ou a exclusão lógica de um item do pedido de compra, impedindo etapas posteriores como entrada de mercadoria ou faturamento. Este é um evento inferido, capturado quando o indicador de exclusão é marcado no item do pedido. | ||
Por que é importante Esta é uma atividade terminal que indica que um pedido foi cancelado. Analisar por que e quando pedidos são excluídos pode revelar problemas no planejamento da demanda ou na seleção de fornecedores. Onde obter Inferido a partir dos documentos de alteração (CDHDR/CDPOS) que mostram o indicador de exclusão (EKPO-LOEKZ) sendo definido como 'L' para um item do pedido de compra. Captura Identifique o timestamp nos documentos de alteração quando o indicador EKPO-LOEKZ for definido. Tipo de evento inferred | |||
Pedido de Compra rejeitado | Esta atividade ocorre quando um aprovador rejeita um pedido de compra durante o workflow de aprovação. É um evento inferido, derivado de uma mudança de status nos dados da estratégia de liberação do PO, indicando que houve rejeição. | ||
Por que é importante Acompanhar rejeições ajuda a identificar problemas de qualidade dos dados do PO, não conformidades com políticas ou falhas na matriz de aprovação. Isso costuma gerar retrabalho e aumentar o tempo de ciclo. Onde obter Inferido a partir dos documentos de alteração (CDHDR/CDPOS) do status de liberação do pedido de compra. Uma rejeição geralmente é registrada quando um código de liberação é cancelado ou quando um status específico de rejeição é definido. Captura Monitore os logs de alteração para identificar o cancelamento de um código de liberação ou mudanças de status que indiquem rejeição. Tipo de evento inferred | |||
Requisição de Compra Aprovada | Representa a aprovação formal de uma requisição de compra, autorizando sua conversão em um pedido de compra. Esse evento é inferido a partir de mudanças nos campos de status de liberação da requisição, conforme rastreado pelo workflow de estratégia de liberação do SAP. | ||
Por que é importante Acompanhar aprovações é crucial para identificar gargalos antes da emissão do pedido e garantir a conformidade com as políticas de aprovação. Atrasos aqui impactam diretamente o tempo de ciclo geral de compras. Onde obter Inferido a partir dos logs de alteração da tabela de Requisição de Compras (EBAN), monitorando especificamente mudanças nos campos de status de liberação (por ex., EBAN-FRGZU) ou analisando documentos de alteração em CDHDR/CDPOS para o objeto EBAN. Captura Monitore os documentos de alteração nos campos de status de liberação da EBAN para identificar a data e hora da aprovação final. Tipo de evento inferred | |||
Guias de Extração
Etapas
- Crie o programa ABAP: Abra o ABAP Editor pela transação SE38. Informe um nome para o novo programa, por exemplo Z_PM_PO_EXTRACT, e clique em 'Create'. Dê um título como 'Process Mining PO Data Extraction' e defina o tipo como 'Executable Program'.
- Configure a tela de seleção: No programa, defina os parâmetros da tela de seleção. Assim, os usuários podem filtrar os dados que querem extrair. Os principais parâmetros incluem o intervalo de datas de criação do Pedido de Compra, o Código da Empresa (BUKRS) e o Tipo de Documento de Compras (BSART).
- Defina as estruturas de dados: Declare uma tabela interna que siga o formato final do Event Log. Essa estrutura deve incluir todos os atributos obrigatórios e recomendados: PurchaseOrder, Activity, EventTime, UserName, VendorNumber, OrderAmount, MaterialGroup, CompanyCode e DocumentType.
- Implemente a lógica de seleção de dados: Escreva a lógica ABAP principal para selecionar os dados de cada uma das 14 atividades obrigatórias. Isso envolve consultar várias tabelas SAP, como EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS e NAST. Use uma subrotina (PERFORM) separada para cada atividade para manter o código organizado.
- Selecione dados de Requisição de Compra: Consulte a tabela EBAN para os eventos 'Requisição de Compra criada', vinculando-os aos Pedidos de Compra por meio da tabela EKPO. Use as tabelas de log de alterações (CDHDR, CDPOS) para identificar eventos de 'Requisição de Compra aprovada', rastreando alterações nos campos de status de liberação.
- Selecione eventos centrais do Pedido de Compra: Consulte as tabelas EKKO e EKPO para o evento 'Pedido de Compra criado'. Use as tabelas de log de alterações (CDHDR, CDPOS) no objeto EINKBELEG para extrair os eventos 'Pedido de Compra alterado', 'Pedido de Compra aprovado', 'Pedido de Compra rejeitado', 'Pedido de Compra concluído' e 'Pedido de Compra excluído', com base em alterações em campos específicos, como indicadores de liberação e indicadores de exclusão.
- Selecione eventos de comunicação do Pedido de Compra (PO): Consulte a tabela NAST para encontrar registros em que o Pedido de Compra foi transmitido com sucesso e capture a atividade 'Pedido de Compra enviado ao fornecedor'.
- Selecione eventos de materiais e serviços: Consulte a tabela EKBE para lançamentos de documentos de material e identifique as atividades 'Entrada de mercadorias registrada' e 'Devolução registrada' com base no tipo de movimento. Consulte ESSR e ESLL para folhas de entrada de serviço e capture 'Confirmação de serviços registrada'.
- Selecione eventos de Gestão da Qualidade: Se o módulo de Gestão da Qualidade estiver em uso, consulte as tabelas QALS e QAVE para identificar quando foi registrada a decisão de uso para um lote de inspeção vinculado a um Pedido de Compra, representando a atividade 'Inspeção de qualidade realizada'.
- Combine e formate os dados: Consolide os dados de todas as seleções em uma única tabela interna final. Garanta que o campo EventTime esteja formatado de forma consistente (por exemplo, YYYY-MM-DDTHH:MI:SS).
- Implemente o download do arquivo: Adicione a funcionalidade para baixar a tabela interna final como arquivo. O formato recomendado é TSV (tabulado) ou CSV, que pode ser gerado com o módulo de função GUI_DOWNLOAD.
- Execute e salve: Execute o programa pelas transações SE38 ou SA38. Preencha os critérios de seleção e execute o relatório. Quando solicitado, salve o arquivo de saída no seu computador com a extensão .csv, pronto para upload.
Configuração
- Intervalo de datas: É fundamental definir um intervalo específico de datas para a extração, geralmente com base na data de criação do pedido de compra (PO) (EKKO-AEDAT). Um intervalo de 3 a 6 meses costuma ser um bom ponto de partida para equilibrar volume de dados e insights de processo.
- Código da empresa (BUKRS): Filtre por um ou mais códigos de empresa para restringir a extração às entidades legais relevantes. Esse parâmetro é essencial para desempenho e relevância.
- Tipo de documento de compra (BSART): Filtre por tipos específicos (ex.: 'NB' para pedido de compra padrão) para focar a análise nos processos padrão e excluir modalidades especiais de suprimento quando necessário.
- Granularidade dos dados: A extração é feita no nível do item do pedido de compra. O Case ID é o número do pedido (EBELN). Todos os eventos, inclusive os do nível de item, como entradas de mercadorias, são vinculados a esse Case ID principal.
- Desempenho: Para grandes volumes de dados, agende o programa como job em background (SM36) para evitar erros de timeout. Garanta que existam índices nos campos-chave usados em cláusulas WHERE, especialmente nas tabelas CDHDR e CDPOS.
- Pré-requisitos: O usuário que executa o relatório precisa de autorização para acessar o ABAP Workbench (SE38), com permissões de desenvolvimento e execução do programa. Também precisa de permissão de leitura em todas as tabelas base, incluindo EKKO, EKPO, EKBE, CDHDR, CDPOS, EBAN, NAST, ESSR e nas tabelas de QM.
a Consulta de Exemplo abap
REPORT Z_PM_PO_EXTRACT.
TABLES: ekko, ekpo, eban.
*&---------------------------------------------------------------------*
*& Data Structures for Event Log
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
purchaseorder TYPE ebeln,
activity TYPE string,
eventtime TYPE timestamp,
username TYPE ernam,
vendornumber TYPE lifnr,
orderamount TYPE netwr_ak,
materialgroup TYPE matkl,
companycode TYPE bukrs,
documenttype TYPE bsart,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_aedat FOR ekko-aedat OBLIGATORY, " PO Creation Date
s_bukrs FOR ekko-bukrs, " Company Code
s_bsart FOR ekko-bsart, " PO Document Type
s_ebeln FOR ekko-ebeln. " PO Number
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_po_headers.
IF gt_event_log IS NOT INITIAL.
PERFORM get_pr_created.
PERFORM get_pr_approved.
PERFORM get_po_created.
PERFORM get_po_release_events. " Approved, Rejected, Approval Requested
PERFORM get_po_sent_to_vendor.
PERFORM get_po_changed.
PERFORM get_goods_receipt_posted.
PERFORM get_services_confirmed.
PERFORM get_quality_inspection.
PERFORM get_goods_returned.
PERFORM get_po_completed.
PERFORM get_po_deleted.
PERFORM download_to_csv.
ELSE.
MESSAGE 'No Purchase Orders found for the given criteria.' TYPE 'I'.
ENDIF.
*&---------------------------------------------------------------------*
*& Form GET_PO_HEADERS (Base data)
*&---------------------------------------------------------------------*
FORM get_po_headers.
SELECT h~ebeln, h~lifnr, h~bukrs, h~bsart, p~netwr, p~matkl
FROM ekko AS h
INNER JOIN ekpo AS p ON h~ebeln = p~ebeln
INTO TABLE @DATA(lt_po_base)
WHERE h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND h~bsart IN @s_bsart
AND h~ebeln IN @s_ebeln.
SORT lt_po_base BY ebeln.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PR_CREATED
*&---------------------------------------------------------------------*
FORM get_pr_created.
DATA: lt_pr_events TYPE TABLE OF ty_event_log.
SELECT p~ebeln AS purchaseorder,
'Purchase Requisition Created' AS activity,
b~erdat AS event_date,
'000000' AS event_time,
b~ernam AS username,
h~lifnr AS vendornumber,
p~netwr AS orderamount,
p~matkl AS materialgroup,
h~bukrs AS companycode,
h~bsart AS documenttype
FROM ekpo AS p
JOIN eban AS b ON p~banfn = b~banfn AND p~bnfpo = b~bnfpo
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE p~ebeln IN @s_ebeln
AND p~banfn IS NOT NULL AND p~banfn <> ''
AND h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND h~bsart IN @s_bsart
INTO TABLE @DATA(lt_pr_created).
LOOP AT lt_pr_created ASSIGNING FIELD-SYMBOL(<fs_pr>).
DATA(ls_event) = CORRESPONDING ty_event_log(<fs_pr>).
CONCATENATE <fs_pr>-event_date <fs_pr>-event_time INTO DATA(lv_ts).
CONVERT DATE <fs_pr>-event_date TIME '000000' INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PR_APPROVED
*&---------------------------------------------------------------------*
FORM get_pr_approved.
DATA: lt_pr_list TYPE TABLE OF eban-banfn.
SELECT DISTINCT p~banfn FROM ekpo AS p
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE h~aedat IN @s_aedat
AND h~bukrs IN @s_bukrs
AND p~banfn IS NOT NULL AND p~banfn <> ''
INTO TABLE @lt_pr_list.
IF lt_pr_list IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime, p~fname, p~value_new
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectid = p~objectid AND h~changenr = p~changenr
FOR ALL ENTRIES IN @lt_pr_list
WHERE h~objectclas = 'BANF'
AND h~objectid = @lt_pr_list-table_line
AND p~tabname = 'EBAN'
AND p~fname = 'FRGZU'
INTO TABLE @DATA(lt_cd_pr).
LOOP AT lt_cd_pr ASSIGNING FIELD-SYMBOL(<fs_cd>) WHERE <fs_cd>-value_new = 'X'.
SELECT SINGLE p~ebeln, p~netwr, p~matkl, h~lifnr, h~bukrs, h~bsart
FROM ekpo AS p
JOIN ekko AS h ON p~ebeln = h~ebeln
WHERE p~banfn = @<fs_cd>-objectid(10)
INTO @DATA(ls_po_info).
IF sy-subrc = 0.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = ls_po_info-ebeln
activity = 'Purchase Requisition Approved'
username = <fs_cd>-username
vendornumber = ls_po_info-lifnr
orderamount = ls_po_info-netwr
materialgroup = ls_po_info-matkl
companycode = ls_po_info-bukrs
documenttype = ls_po_info-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_CREATED
*&---------------------------------------------------------------------*
FORM get_po_created.
LOOP AT lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>).
SELECT SINGLE aedat, ernam FROM ekko INTO @DATA(ls_ekko)
WHERE ebeln = @<fs_po>-ebeln.
IF sy-subrc = 0.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Created'
username = ls_ekko-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE ls_ekko-aedat TIME '000000' INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_RELEASE_EVENTS
*&---------------------------------------------------------------------*
FORM get_po_release_events.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime, p~value_new
FROM cdhdr AS h
JOIN cdpos AS p ON h~objectid = p~objectid AND h~changenr = p~changenr
WHERE h~objectclas = 'EINKBELEG'
AND h~objectid IN lt_ebeln
AND p~tabname = 'EKKO'
AND p~fname = 'FRGKE'
INTO TABLE @DATA(lt_cd_po).
LOOP AT lt_cd_po ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
CASE <fs_cd>-value_new.
WHEN '2' OR 'R'. " Final Release
ls_event-activity = 'Purchase Order Approved'.
WHEN '1'. " Blocked
ls_event-activity = 'Purchase Order Rejected'.
WHEN OTHERS. " Any other change implies a pending state
ls_event-activity = 'Purchase Order Approval Requested'.
ENDCASE.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_SENT_TO_VENDOR
*&---------------------------------------------------------------------*
FORM get_po_sent_to_vendor.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT objky, erdat, eruhr, ernam
FROM nast
WHERE kapol = 'EF' AND objky IN lt_ebeln AND vstat = '1'
INTO TABLE @DATA(lt_nast).
LOOP AT lt_nast ASSIGNING FIELD-SYMBOL(<fs_nast>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_nast>-objky.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Sent to Vendor'
username = <fs_nast>-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_nast>-erdat TIME <fs_nast>-eruhr INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_CHANGED
*&---------------------------------------------------------------------*
FORM get_po_changed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT DISTINCT objectid, username, udate, utime
FROM cdhdr
WHERE objectclas = 'EINKBELEG' AND objectid IN lt_ebeln AND tcode <> 'ME21N' AND tcode <> 'ME22'
INTO TABLE @DATA(lt_cdhdr_chg).
LOOP AT lt_cdhdr_chg ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Changed'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_GOODS_RECEIPT_POSTED
*&---------------------------------------------------------------------*
FORM get_goods_receipt_posted.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT k~ebeln, m~cpudt, m~cputm, m~usnam, k~bewtp
FROM ekbe AS k JOIN mkpf AS m ON k~belnr = m~mblnr AND k~gjahr = m~mjahr
WHERE k~ebeln IN lt_ebeln AND k~bewtp = 'E' AND k~shkzg = 'S'
INTO TABLE @DATA(lt_gr).
LOOP AT lt_gr ASSIGNING FIELD-SYMBOL(<fs_gr>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_gr>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Goods Receipt Posted'
username = <fs_gr>-usnam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_gr>-cpudt TIME <fs_gr>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_SERVICES_CONFIRMED
*&---------------------------------------------------------------------*
FORM get_services_confirmed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT l~ebeln, h~erdat, h~eruhr, h~ernam
FROM essr AS h JOIN esll AS l ON h~lblni = l~lblni
WHERE l~ebeln IN lt_ebeln
INTO TABLE @DATA(lt_ses).
LOOP AT lt_ses ASSIGNING FIELD-SYMBOL(<fs_ses>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_ses>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Services Confirmation Entered'
username = <fs_ses>-ernam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_ses>-erdat TIME <fs_ses>-eruhr INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_QUALITY_INSPECTION
*&---------------------------------------------------------------------*
FORM get_quality_inspection.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT q~ebeln, v~vdatum, v~vzeit, v~vname
FROM qals AS q JOIN qave AS v ON q~prueflos = v~prueflos
WHERE q~ebeln IN lt_ebeln
INTO TABLE @DATA(lt_qm).
LOOP AT lt_qm ASSIGNING FIELD-SYMBOL(<fs_qm>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_qm>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Quality Inspection Performed'
username = <fs_qm>-vname
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_qm>-vdatum TIME <fs_qm>-vzeit INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_GOODS_RETURNED
*&---------------------------------------------------------------------*
FORM get_goods_returned.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT k~ebeln, m~cpudt, m~cputm, m~usnam
FROM ekbe AS k JOIN mkpf AS m ON k~belnr = m~mblnr AND k~gjahr = m~mjahr
WHERE k~ebeln IN lt_ebeln AND k~bwart = '122'
INTO TABLE @DATA(lt_ret).
LOOP AT lt_ret ASSIGNING FIELD-SYMBOL(<fs_ret>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_ret>-ebeln.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Goods Returned'
username = <fs_ret>-usnam
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_ret>-cpudt TIME <fs_ret>-cputm INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_COMPLETED
*&---------------------------------------------------------------------*
FORM get_po_completed.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime
FROM cdhdr AS h JOIN cdpos AS p ON h~changenr = p~changenr AND h~objectid = p~objectid
WHERE h~objectclas = 'EINKBELEG' AND h~objectid IN lt_ebeln AND p~tabname = 'EKPO' AND p~fname = 'ELIKZ' AND p~value_new = 'X'
INTO TABLE @DATA(lt_cd_comp).
LOOP AT lt_cd_comp ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Completed'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_PO_DELETED
*&---------------------------------------------------------------------*
FORM get_po_deleted.
DATA: lt_ebeln TYPE RANGE OF ebeln, ls_ebeln LIKE LINE OF lt_ebeln.
LOOP AT lt_po_base INTO DATA(ls_po_base).
ls_ebeln-sign = 'I'. ls_ebeln-option = 'EQ'. ls_ebeln-low = ls_po_base-ebeln.
APPEND ls_ebeln TO lt_ebeln.
ENDLOOP.
IF lt_ebeln IS INITIAL. RETURN. ENDIF.
SELECT h~objectid, h~username, h~udate, h~utime
FROM cdhdr AS h JOIN cdpos AS p ON h~changenr = p~changenr AND h~objectid = p~objectid
WHERE h~objectclas = 'EINKBELEG' AND h~objectid IN lt_ebeln AND p~tabname = 'EKPO' AND p~fname = 'LOEKZ' AND p~value_new = 'L'
INTO TABLE @DATA(lt_cd_del).
LOOP AT lt_cd_del ASSIGNING FIELD-SYMBOL(<fs_cd>).
READ TABLE lt_po_base ASSIGNING FIELD-SYMBOL(<fs_po>) WITH KEY ebeln = <fs_cd>-objectid.
IF sy-subrc <> 0. CONTINUE. ENDIF.
DATA(ls_event) = VALUE ty_event_log(
purchaseorder = <fs_po>-ebeln
activity = 'Purchase Order Deleted'
username = <fs_cd>-username
vendornumber = <fs_po>-lifnr
orderamount = <fs_po>-netwr
materialgroup = <fs_po>-matkl
companycode = <fs_po>-bukrs
documenttype = <fs_po>-bsart
).
CONVERT DATE <fs_cd>-udate TIME <fs_cd>-utime INTO TIME STAMP ls_event-eventtime TIME ZONE sy-zonlo.
APPEND ls_event TO gt_event_log.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form DOWNLOAD_TO_CSV
*&---------------------------------------------------------------------*
FORM download_to_csv.
DATA: lv_filename TYPE string.
DATA: lt_fieldnames TYPE TABLE OF string.
APPEND 'PurchaseOrder' TO lt_fieldnames.
APPEND 'Activity' TO lt_fieldnames.
APPEND 'EventTime' TO lt_fieldnames.
APPEND 'UserName' TO lt_fieldnames.
APPEND 'VendorNumber' TO lt_fieldnames.
APPEND 'OrderAmount' TO lt_fieldnames.
APPEND 'MaterialGroup' TO lt_fieldnames.
APPEND 'CompanyCode' TO lt_fieldnames.
APPEND 'DocumentType' TO lt_fieldnames.
DATA(lv_header) = REDUCE string( INIT h = '' FOR f IN lt_fieldnames NEXT h = h && f && cl_abap_char_utilities=>horizontal_tab ).
REPLACE LAST OCCURRENCE OF cl_abap_char_utilities=>horizontal_tab IN lv_header WITH cl_abap_char_utilities=>cr_lf.
DATA(lv_file_content) = lv_header.
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_log>).
DATA lv_line TYPE string.
DATA lv_eventtime_str TYPE string.
lv_eventtime_str = |{ <fs_log>-eventtime TIMESTAMP = ISO }|.
lv_line = <fs_log>-purchaseorder && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-activity && cl_abap_char_utilities=>horizontal_tab &&
lv_eventtime_str && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-username && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-vendornumber && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-orderamount && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-materialgroup && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-companycode && cl_abap_char_utilities=>horizontal_tab &&
<fs_log>-documenttype && cl_abap_char_utilities=>cr_lf.
CONCATENATE lv_file_content lv_line INTO lv_file_content.
ENDLOOP.
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
filename = 'C:\temp\po_event_log.csv'
filetype = 'ASC'
CHANGING
data_tab = lv_file_content.Etapas
- Estabeleça a conexão com o banco de dados: Obtenha credenciais de leitura e os dados de conexão (hostname, porta, nome do banco) do banco de dados do SAP ECC. Garanta que as ferramentas cliente necessárias, como DBeaver, SQL Developer ou SSMS, estejam instaladas.
- Identifique o schema SAP: Conecte-se ao banco e identifique o schema SAP principal onde ficam as tabelas. Geralmente é SAPSR3, SAPHANADB ou um nome similar específico do sistema. Você precisará prefixar todos os nomes de tabela na consulta com esse schema se ele não for o padrão do seu usuário.
- Revise a consulta SQL: Abra o script SQL fornecido na sua ferramenta. Essa consulta abrangente foi criada para extrair 14 atividades distintas do processo Purchase-to-Pay (P2P), combinando várias tabelas SAP.
- Personalize os parâmetros da consulta: Localize a Common Table Expression (CTE) PO_BASE no início do script. Ajuste os placeholders para definir o escopo da extração:
- [START_DATE] e [END_DATE]: Defina o intervalo de datas da análise (por exemplo, '20230101' e '20230630'). Recomenda-se filtrar pelo campo AEDAT (Alterado em).
- [COMPANY_CODE_1], [COMPANY_CODE_2]: Especifique os Company Codes do SAP que deseja incluir.
- [DOC_TYPE_1], [DOC_TYPE_2]: Informe os Tipos de Documento de Pedido de Compra (PO) a incluir.
- [Your SAP Schema]: Substitua este placeholder pelo nome do seu schema SAP em todo o script.
- Execute a consulta: Execute o script SQL personalizado no banco do SAP. O tempo de execução vai variar conforme o período, o volume de dados e a performance do banco.
- Revise os resultados: Quando a consulta terminar, faça uma verificação rápida do resultado. Veja se a quantidade de linhas faz sentido e se colunas essenciais como PurchaseOrder, Activity e EventTime foram preenchidas como esperado.
- Exporte os dados para CSV: Exporte todo o conjunto de resultados do seu cliente SQL para um arquivo CSV. Use codificação UTF-8 para evitar problemas de caracteres.
- Prepare para o upload: Garanta que os cabeçalhos das colunas no CSV correspondam exatamente aos nomes de atributos exigidos: PurchaseOrder, Activity, EventTime, UserName, VendorNumber, OrderAmount, MaterialGroup, CompanyCode, DocumentType.
- Faça o upload na ferramenta de Process Mining: Envie o arquivo CSV final para sua aplicação de Process Mining para análise e visualização.
Configuração
- Pré-requisitos: É necessário acesso direto, somente leitura, ao banco de dados do SAP ECC. Os usuários precisam de autorização suficiente para consultar tabelas como EKKO, EKPO, EKBE, EBAN, CDHDR, CDPOS e NAST.
- Filtro de período: É fundamental aplicar um intervalo de datas para limitar o volume de dados. Filtrar EKKO.AEDAT (data de alteração da PO) por um período de 3 a 6 meses é um ponto de partida comum. Intervalos muito amplos podem gerar tempos de execução extremamente longos.
- Filtros-chave: Para garantir uma análise focada, sempre filtre por EKKO.BUKRS (código da empresa) e EKKO.BSART (tipo de documento). Isso restringe o escopo às entidades legais e aos processos relevantes.
- Considerações de desempenho: A consulta faz junções (joins) entre várias tabelas grandes, incluindo as de histórico de alterações (CDHDR, CDPOS). Isso pode consumir muitos recursos. Recomenda-se fortemente executar essa extração fora do horário de pico ou em um banco replicado, fora de produção, para evitar impacto no desempenho do sistema.
- Registro de alterações: A precisão de atividades como "Aprovado", "Rejeitado", "Concluído" e "Alterado" depende de o registro (logging) de alterações estar ativo para os campos relevantes no SAP. Confirme com o administrador do SAP se esse registro está habilitado (transação SCDO).
a Consulta de Exemplo sql
WITH PO_BASE AS (
SELECT
H.EBELN, -- Purchase Order Number
I.EBELP, -- Purchase Order Item
H.LIFNR, -- Vendor Number
H.BUKRS, -- Company Code
H.BSART, -- Document Type
I.NETWR, -- Order Amount (Item Level)
I.MATKL, -- Material Group
I.BANFN, -- Purchase Requisition Number
I.BNFPO -- Purchase Requisition Item
FROM [Your SAP Schema].EKKO AS H
JOIN [Your SAP Schema].EKPO AS I ON H.EBELN = I.EBELN
WHERE H.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' -- Filter on PO Change Date, e.g., '20230101' and '20231231'
AND H.BUKRS IN ('[COMPANY_CODE_1]', '[COMPANY_CODE_2]') -- Specify Company Codes
AND H.BSART IN ('[DOC_TYPE_1]', '[DOC_TYPE_2]') -- Specify PO Document Types
)
-- 1. Purchase Requisition Created
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Requisition Created' AS "Activity",
TO_TIMESTAMP(CONCAT(pr.ERDAT, '000000'), 'YYYYMMDDHH24MISS') AS "EventTime", -- Time is not available in EBAN
pr.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EBAN pr ON po.BANFN = pr.BANFN AND po.BNFPO = pr.BNFPO
WHERE po.BANFN IS NOT NULL AND po.BANFN <> ''
UNION ALL
-- 2. Purchase Requisition Approved
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Requisition Approved' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'BANF' AND ch.OBJECTID = po.BANFN
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EBAN' AND cp.FNAME = 'FRGZU' AND cp.VALUE_NEW = 'X' -- Release indicator set to 'released'
UNION ALL
-- 3. Purchase Order Created
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Created' AS "Activity",
TO_TIMESTAMP(CONCAT(ekko.ERDAT, ' ', ekko.ERZET), 'YYYYMMDD HH24MISS') AS "EventTime",
ekko.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKKO ekko ON po.EBELN = ekko.EBELN
UNION ALL
-- 4. Purchase Order Approval Requested / 5. Approved / 6. Rejected (from Change Docs)
SELECT
po.EBELN AS "PurchaseOrder",
CASE
WHEN cp.VALUE_NEW > cp.VALUE_OLD THEN 'Purchase Order Approval Requested'
WHEN cp.VALUE_NEW = ekko.FRGKE AND ekko.FRGKE = 'R' THEN 'Purchase Order Approved'
ELSE 'Purchase Order Rejected' -- Simplified logic, may need adjustment
END AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKKO ekko ON po.EBELN = ekko.EBELN
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID = po.EBELN
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKKO' AND cp.FNAME = 'FRGZU' -- Release status
UNION ALL
-- 7. Purchase Order Sent to Vendor
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Sent to Vendor' AS "Activity",
TO_TIMESTAMP(CONCAT(na.ERDAT, ' ', na.ERUHR), 'YYYYMMDD HH24MISS') AS "EventTime",
na.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].NAST na ON na.OBJKY = po.EBELN AND na.KSCHL = '[Your PO Output Type]' -- e.g., 'NEU'
WHERE na.VSTAT = '1' -- Successfully processed
UNION ALL
-- 8. Purchase Order Changed
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Changed' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID = po.EBELN
WHERE ch.TCODE IN ('ME22', 'ME22N') -- Filter for change transactions
UNION ALL
-- 9. Goods Receipt Posted
SELECT
ekbe.EBELN AS "PurchaseOrder",
'Goods Receipt Posted' AS "Activity",
TO_TIMESTAMP(CONCAT(mkpf.CPUDT, ' ', mkpf.CPUTM), 'YYYYMMDD HH24MISS') AS "EventTime",
mkpf.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM [Your SAP Schema].EKBE AS ekbe
JOIN [Your SAP Schema].MKPF AS mkpf ON ekbe.BELNR = mkpf.MBLNR AND ekbe.GJAHR = mkpf.MJAHR
JOIN PO_BASE AS po ON ekbe.EBELN = po.EBELN AND ekbe.EBELP = po.EBELP
WHERE ekbe.BEWTP = 'E' -- Goods Receipt
AND ekbe.SHKZG = 'S' -- Debit/Credit Indicator: Goods Receipt
UNION ALL
-- 10. Services Confirmation Entered
SELECT
po.EBELN AS "PurchaseOrder",
'Services Confirmation Entered' AS "Activity",
TO_TIMESTAMP(CONCAT(essr.ERDAT, ' ', essr.ERZET), 'YYYYMMDD HH24MISS') AS "EventTime",
essr.ERNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKBE ekbe ON po.EBELN = ekbe.EBELN AND po.EBELP = ekbe.EBELP
JOIN [Your SAP Schema].ESSR essr ON ekbe.LBLNI = essr.LBLNI
WHERE ekbe.BEWTP = 'L' -- Service Entry Sheet
UNION ALL
-- 11. Quality Inspection Performed
SELECT
po.EBELN AS "PurchaseOrder",
'Quality Inspection Performed' AS "Activity",
TO_TIMESTAMP(CONCAT(qave.VDATUM, ' ', qave.VZEIT), 'YYYYMMDD HH24MISS') AS "EventTime",
qave.VNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].EKBE ekbe ON po.EBELN = ekbe.EBELN AND po.EBELP = ekbe.EBELP
JOIN [Your SAP Schema].QALS qals ON qals.MBLNR = ekbe.BELNR AND qals.MJAHR = ekbe.GJAHR
JOIN [Your SAP Schema].QAVE qave ON qals.PRUEFLOS = qave.PRUEFLOS
WHERE ekbe.BEWTP = 'E' -- Linked to a Goods Receipt
UNION ALL
-- 12. Goods Returned
SELECT
ekbe.EBELN AS "PurchaseOrder",
'Goods Returned' AS "Activity",
TO_TIMESTAMP(CONCAT(mkpf.CPUDT, ' ', mkpf.CPUTM), 'YYYYMMDD HH24MISS') AS "EventTime",
mkpf.USNAM AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM [Your SAP Schema].EKBE AS ekbe
JOIN [Your SAP Schema].MKPF AS mkpf ON ekbe.BELNR = mkpf.MBLNR AND ekbe.GJAHR = mkpf.MJAHR
JOIN PO_BASE AS po ON ekbe.EBELN = po.EBELN AND ekbe.EBELP = po.EBELP
WHERE ekbe.BEWTP = 'E' -- Goods Movement
AND ekbe.SHKZG = 'H' -- Debit/Credit Indicator: Return
AND ekbe.BWART = '122' -- Movement type for return to vendor
UNION ALL
-- 13. Purchase Order Completed
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Completed' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID LIKE CONCAT(po.EBELN, po.EBELP, '%')
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKPO' AND cp.FNAME = 'ELIKZ' AND cp.VALUE_NEW = 'X' -- Delivery completed indicator
UNION ALL
-- 14. Purchase Order Deleted
SELECT
po.EBELN AS "PurchaseOrder",
'Purchase Order Deleted' AS "Activity",
TO_TIMESTAMP(CONCAT(ch.UDATE, ' ', ch.UTIME), 'YYYYMMDD HH24MISS') AS "EventTime",
ch.USERNAME AS "UserName",
po.LIFNR AS "VendorNumber",
po.NETWR AS "OrderAmount",
po.MATKL AS "MaterialGroup",
po.BUKRS AS "CompanyCode",
po.BSART AS "DocumentType"
FROM PO_BASE po
JOIN [Your SAP Schema].CDHDR ch ON ch.OBJECTCLASS = 'EINKBELEG' AND ch.OBJECTID LIKE CONCAT(po.EBELN, po.EBELP, '%')
JOIN [Your SAP Schema].CDPOS cp ON ch.OBJECTCLASS = cp.OBJECTCLASS AND ch.OBJECTID = cp.OBJECTID AND ch.CHANGENR = cp.CHANGENR
WHERE cp.TABNAME = 'EKPO' AND cp.FNAME = 'LOEKZ' AND cp.VALUE_NEW = 'L'; -- Deletion indicatorEtapas
- Pré-requisitos e conexão: Garanta que sua ferramenta de ETL de terceiros esteja com o SAP Certified Connector instalado e licenciado. No console de administração da sua ferramenta, configure uma nova conexão com o seu sistema SAP ECC. Você vai precisar do host do servidor de aplicação, número do sistema, mandante e de um usuário SAP dedicado com autorizações RFC e de leitura de tabelas.
- Identifique as tabelas de origem: No seu job de ETL ou fluxo de dados, defina as tabelas SAP necessárias como origens. As principais são: EKKO (cabeçalho do pedido), EKPO (item do pedido), EBAN (requisição de compra), CDHDR (cabeçalho de documento de alteração), CDPOS (item de documento de alteração), MSEG (segmento de documento: material), MKPF (cabeçalho de documento de material), NAST (status de mensagem), ESSR (cabeçalho da folha de serviços) e QALS (lote de inspeção).
- Extraia 'Purchase Order Created': Crie um fluxo de dados a partir da tabela EKKO. Filtre os registros pelo período desejado (por exemplo, usando AEDAT) e pelo escopo organizacional (por exemplo, BUKRS para código da empresa e BSART para tipo de documento). Mapeie EKKO.EBELN para PurchaseOrder, 'Purchase Order Created' para Activity e combine AEDAT e ERZET para compor o EventTime. Mapeie também os demais atributos necessários.
- Extraia 'Goods Receipt Posted': Crie um fluxo de dados separado a partir da MSEG e faça join com a MKPF em MBLNR e MJAHR. Filtre pelos tipos de movimento relevantes, como '101'. Mapeie MSEG.EBELN para PurchaseOrder, 'Goods Receipt Posted' para Activity e use MKPF.CPUDT e MKPF.CPUTM para o EventTime.
- Extraia eventos baseados em alterações (aprovações, mudanças, exclusões): Crie um fluxo de dados usando CDHDR e CDPOS, ligados por CHANGENR. Essa única origem permite derivar várias atividades.
- Filtre por OBJECTCLAS = 'EINKBELEG' e TABNAME = 'EKPO'.
- Para 'Purchase Order Approved', filtre alterações no campo de status de liberação (por exemplo, FNAME = 'FRGZU') em que o novo valor (VALUE_NEW) indique aprovação final.
- Para 'Purchase Order Deleted', filtre alterações no indicador de exclusão (FNAME = 'LOEKZ') em que o novo valor seja 'L'.
- Para 'Purchase Order Changed', filtre outras alterações de campos relevantes, excluindo os campos de status usados nas demais atividades.
- Para todos esses eventos, use CDHDR.UDATE e CDHDR.UTIME como EventTime.
- Extraia eventos de 'Purchase Requisition': Crie um fluxo de dados a partir da EBAN para 'Purchase Requisition Created'. Para vincular ao caso PurchaseOrder, faça join da EBAN com a EKPO usando o número da requisição (BANFN) e o item (BNFPO). Para 'Purchase Requisition Approved', use CDHDR/CDPOS com OBJECTCLAS = 'BANF'. Isso exige um mapeamento cuidadoso para garantir que o evento seja associado ao pedido de compra gerado.
- Extraia 'PO Sent to Vendor': Crie um fluxo de dados a partir da NAST. Filtre por OBJECTKEY (que contém o número do PO), pelo tipo de saída (KSCHL) e por status de processamento concluído com sucesso (VSTAT = '1'). Use ERDAT e UHR para o EventTime.
- Una os fluxos de atividades: Use uma transformação 'Union' ou 'Merge' na sua ferramenta de ETL para combinar as saídas de todos os fluxos de dados criados nas etapas anteriores. Garanta que os nomes de colunas e os tipos de dados sejam consistentes entre os fluxos (PurchaseOrder, Activity, EventTime, etc.).
- Conversão de tipos e formatos: Converta a coluna EventTime para um formato de timestamp consistente (por exemplo, YYYY-MM-DD HH:MM:SS). Converta OrderAmount para um formato decimal padrão.
- Defina o destino: Configure um destino (target) ou 'sink' para o fluxo de dados consolidado. Normalmente, é um arquivo plano, como CSV ou Parquet. Ajuste o delimitador, os qualificadores de texto e as opções de cabeçalho.
- Execute e valide: Execute o job completo de ETL. Faça verificações no arquivo de saída para garantir que as 14 atividades estejam presentes, que a quantidade de linhas seja coerente e que os atributos-chave estejam preenchidos corretamente.
- Agende e exporte: Depois de validado, agende o job de ETL para execução periódica (por exemplo, à noite) para manter os dados atualizados. O arquivo gerado está pronto para upload na sua ferramenta de Process Mining.
Configuração
- Pré-requisitos: Uma ferramenta ETL comercial (ex.: Informatica PowerCenter, Talend, SAP Data Services) com o conector SAP Certified correspondente para o ECC. Um usuário de diálogo ou de sistema no SAP com autorizações S_RFC e S_TABU_DIS para as tabelas necessárias.
- Conexão SAP: O conector deve ser configurado com servidor de aplicação, número do sistema, mandante, usuário e senha. Recomenda-se o uso de Secure Network Communications (SNC).
- Filtro de período: É crucial aplicar um filtro de datas para limitar o volume de dados. Prática comum: filtrar EKKO.AEDAT (data de criação do pedido de compra - PO) dos últimos 3 a 12 meses. Esse filtro deve ser aplicado na origem para evitar extrair dados em excesso do SAP.
- Filtros de escopo organizacional: Sempre filtre por EKKO.BUKRS (código da empresa) e considere filtrar por EKPO.WERKS (Centro) ou EKKO.EKORG (Organização de Compras) para reduzir a análise a uma unidade de negócio específica.
- Filtro por tipo de documento: Use EKKO.BSART para incluir apenas os tipos de pedido de compra relevantes e excluir transferências de estoque ou outros documentos internos que não fazem parte do processo P2P padrão.
- Otimização de desempenho: A extração das tabelas de documentos de alteração (CDHDR, CDPOS) pode ser lenta. Garanta a aplicação de filtros em OBJECTCLAS, OBJECTID e UDATE. Ajuste a configuração "Packet Size" no conector SAP para otimizar a taxa de transferência. Em ambientes muito grandes, considere uma carga histórica inicial seguida de cargas delta agendadas.
a Consulta de Exemplo config
/*
This is a logical representation of the transformations performed within the ETL tool.
The tool's graphical interface will be used to configure these separate data flows, which are then combined with a UNION transformation.
Placeholders like [Your ETL Tool Functions] and [Filter Values] must be configured in the tool.
*/
-- 1. Purchase Requisition Created
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Requisition Created' AS Activity,
[Your ETL Tool Functions].DateTime(eban.ERDAT, eban.ERZET) AS EventTime,
eban.ERNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM EBAN AS eban
INNER JOIN EKPO AS ekpo ON eban.BANFN = ekpo.BANFN AND eban.BNFPO = ekpo.BNFPO
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 2. Purchase Requisition Approved (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Requisition Approved' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EBAN AS eban ON cdhdr.OBJECTID = eban.BANFN
INNER JOIN EKPO AS ekpo ON eban.BANFN = ekpo.BANFN AND eban.BNFPO = ekpo.BNFPO
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'BANF' AND cdpos.TABNAME = 'EBAN' AND cdpos.FNAME = 'FRGZU' AND cdpos.VALUE_NEW = '[Final Release Indicator for PR]'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 3. Purchase Order Created
SELECT
EBELN AS PurchaseOrder,
'Purchase Order Created' AS Activity,
[Your ETL Tool Functions].DateTime(AEDAT, ERZET) AS EventTime,
ERNAM AS UserName,
LIFNR AS VendorNumber,
NULL AS OrderAmount, -- Amount is at item level
NULL AS MaterialGroup, -- Attribute is at item level
BUKRS AS CompanyCode,
BSART AS DocumentType
FROM EKKO
WHERE AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 4. Purchase Order Approval Requested / 5. Approved / 6. Rejected (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
CASE
WHEN cdpos.VALUE_NEW = '[Final Release Code]' THEN 'Purchase Order Approved'
WHEN cdpos.VALUE_NEW = '[Rejection Release Code]' THEN 'Purchase Order Rejected'
ELSE 'Purchase Order Approval Requested'
END AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKKO AS ekko ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKKO' AND cdpos.FNAME = 'FRGKE'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 7. Purchase Order Sent to Vendor
SELECT
ekko.EBELN AS PurchaseOrder,
'Purchase Order Sent to Vendor' AS Activity,
[Your ETL Tool Functions].DateTime(nast.ERDAT, nast.UHR) AS EventTime,
nast.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM NAST AS nast
INNER JOIN EKKO AS ekko ON nast.OBJKY = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE nast.KAPPL = 'EF' AND nast.VSTAT = '1' AND nast.KSCHL IN ([Your PO Output Types])
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 8. Purchase Order Changed (inferred from change documents, simplified example)
SELECT DISTINCT
ekko.EBELN AS PurchaseOrder,
'Purchase Order Changed' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKKO AS ekko ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekko.EBELN
INNER JOIN EKPO AS ekpo ON ekko.EBELN = ekpo.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.FNAME NOT IN ('FRGKE', 'FRGZU', 'LOEKZ', 'ELIKZ')
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 9. Goods Receipt Posted
SELECT
mseg.EBELN AS PurchaseOrder,
'Goods Receipt Posted' AS Activity,
[Your ETL Tool Functions].DateTime(mkpf.CPUDT, mkpf.CPUTM) AS EventTime,
mkpf.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM MSEG AS mseg
INNER JOIN MKPF AS mkpf ON mseg.MBLNR = mkpf.MBLNR AND mseg.MJAHR = mkpf.MJAHR
INNER JOIN EKPO AS ekpo ON mseg.EBELN = ekpo.EBELN AND mseg.EBELP = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE mseg.BWART = '101' AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 10. Services Confirmation Entered
SELECT
essr.EBELN AS PurchaseOrder,
'Services Confirmation Entered' AS Activity,
[Your ETL Tool Functions].DateTime(essr.ERDAT, essr.ERZET) AS EventTime,
essr.ERNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM ESSR AS essr
INNER JOIN EKKO AS ekko ON essr.EBELN = ekko.EBELN
INNER JOIN EKPO AS ekpo ON essr.EBELN = ekpo.EBELN AND essr.EBELP = ekpo.EBELP
WHERE ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 11. Quality Inspection Performed
SELECT
qals.EBELN AS PurchaseOrder,
'Quality Inspection Performed' AS Activity,
[Your ETL Tool Functions].DateTime(qals.PASTRTERM, '000000') AS EventTime, -- Time is often not available
qals.PRUEFER AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM QALS AS qals
INNER JOIN EKKO AS ekko ON qals.EBELN = ekko.EBELN
INNER JOIN EKPO AS ekpo ON qals.EBELN = ekpo.EBELN AND qals.EBELP = ekpo.EBELP
WHERE qals.VCODE <> '' -- A usage decision code exists
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 12. Goods Returned
SELECT
mseg.EBELN AS PurchaseOrder,
'Goods Returned' AS Activity,
[Your ETL Tool Functions].DateTime(mkpf.CPUDT, mkpf.CPUTM) AS EventTime,
mkpf.USNAM AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM MSEG AS mseg
INNER JOIN MKPF AS mkpf ON mseg.MBLNR = mkpf.MBLNR AND mseg.MJAHR = mkpf.MJAHR
INNER JOIN EKPO AS ekpo ON mseg.EBELN = ekpo.EBELN AND mseg.EBELP = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE mseg.BWART = '122' AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 13. Purchase Order Completed (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Order Completed' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKPO AS ekpo ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekpo.EBELN AND SUBSTRING(cdhdr.OBJECTID, 11, 5) = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKPO' AND cdpos.FNAME = 'ELIKZ' AND cdpos.VALUE_NEW = 'X'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);
UNION ALL
-- 14. Purchase Order Deleted (inferred from change documents)
SELECT
ekpo.EBELN AS PurchaseOrder,
'Purchase Order Deleted' AS Activity,
[Your ETL Tool Functions].DateTime(cdhdr.UDATE, cdhdr.UTIME) AS EventTime,
cdhdr.USERNAME AS UserName,
ekko.LIFNR AS VendorNumber,
ekpo.NETWR AS OrderAmount,
ekpo.MATKL AS MaterialGroup,
ekko.BUKRS AS CompanyCode,
ekko.BSART AS DocumentType
FROM CDHDR AS cdhdr
INNER JOIN CDPOS AS cdpos ON cdhdr.CHANGENR = cdpos.CHANGENR
INNER JOIN EKPO AS ekpo ON SUBSTRING(cdhdr.OBJECTID, 1, 10) = ekpo.EBELN AND SUBSTRING(cdhdr.OBJECTID, 11, 5) = ekpo.EBELP
INNER JOIN EKKO AS ekko ON ekpo.EBELN = ekko.EBELN
WHERE cdhdr.OBJECTCLAS = 'EINKBELEG' AND cdpos.TABNAME = 'EKPO' AND cdpos.FNAME = 'LOEKZ' AND cdpos.VALUE_NEW = 'L'
AND ekko.AEDAT BETWEEN '[START_DATE]' AND '[END_DATE]' AND ekko.BUKRS IN ([YOUR_COMPANY_CODES]);