Mẫu dữ liệu xử lý hóa đơn phải trả
Mẫu dữ liệu xử lý hóa đơn phải trả
- Các thuộc tính nên có để phân tích đầy đủ
- Các hoạt động chính cần theo dõi trong quy trình
- Hướng dẫn từng bước trích xuất dữ liệu
Thuộc tính trong quy trình xử lý hóa đơn phải trả
| Tên | Mô tả | ||
|---|---|---|---|
| Hóa đơn Invoice | Mã định danh duy nhất của chứng từ hóa đơn, được dùng làm mã hồ sơ chính cho quy trình công nợ phải trả. | ||
| Mô tả Hóa đơn là đối tượng trung tâm liên kết mọi hoạt động liên quan, từ lúc nhận đến khi thanh toán. Trong SAP S/4HANA, mã này thường là khóa ghép gồm Mã công ty (BUKRS), Số chứng từ duy nhất (BELNR) và Năm tài chính (GJAHR). Phân tích theo hóa đơn giúp bạn theo dõi toàn bộ vòng đời xử lý. Đây là cơ sở để tính các chỉ số quan trọng như tổng thời gian xử lý, xác định điểm nghẽn ở từng hóa đơn và hiểu các lộ trình khác nhau mà hóa đơn có thể đi qua trong quy trình. Vì sao điều này quan trọng Mã này xác định riêng hành trình của từng hóa đơn, giúp theo dõi toàn bộ vòng đời và phân tích hiệu quả quy trình theo từng trường hợp. Lấy dữ liệu ở đâu Đây là khóa ghép lấy từ các bảng BKPF (phần đầu chứng từ kế toán) hoặc RBKP (phần đầu chứng từ nhận hóa đơn), sử dụng các trường BUKRS, BELNR và GJAHR. Ví dụ 1000-1900000001-20231710-1900000002-20232000-5100000003-2024 | |||
| Hoạt động ActivityName | Tên của một sự kiện hoặc bước nghiệp vụ cụ thể trong vòng đời xử lý hóa đơn. | ||
| Mô tả Hoạt động là một giai đoạn hoặc hành động riêng trong quy trình công nợ phải trả, chẳng hạn 'Nhận hóa đơn', 'Hạch toán hóa đơn' hoặc 'Thực hiện thanh toán'. Đây là những thành phần tạo nên sơ đồ quy trình. Phân tích hoạt động là phần cốt lõi của process mining. Việc này giúp trực quan hóa luồng quy trình, xác định các lộ trình phổ biến, phát hiện sai lệch so với quy trình chuẩn và đo tần suất cũng như thời lượng của từng bước. Trình tự hoạt động của một hóa đơn tạo thành hành trình xử lý hóa đơn đó. Vì sao điều này quan trọng Thuộc tính này xác định các bước trong quy trình, giúp trực quan hóa và phân tích luồng quy trình, tìm điểm nghẽn và phát hiện các vòng lặp làm lại. Lấy dữ liệu ở đâu Được lấy từ nhiều nguồn, gồm thay đổi trạng thái chứng từ (chẳng hạn BKPF-BSTAT), chứng từ thay đổi (các bảng CDHDR/CDPOS) hoặc nhật ký workflow. Thông thường cần xây dựng logic trích xuất riêng. Ví dụ Nhận hóa đơnHóa đơn được phê duyệtThực hiện thanh toánChặn thanh toán hóa đơn | |||
| Thời điểm sự kiện EventTime | Ngày và giờ chính xác khi hoạt động diễn ra. | ||
| Mô tả Thời điểm sự kiện là dấu thời gian gắn với mỗi hoạt động, cho biết thứ tự diễn ra của các sự kiện đối với một hóa đơn. Dữ liệu này cần thiết để hiểu luồng quy trình và thực hiện các phân tích theo thời gian. Khi phân tích, thời điểm sự kiện được dùng để sắp xếp hoạt động đúng thứ tự, tính thời gian giữa các bước, xác định thời gian chờ và phân tích hiệu quả quy trình theo từng giai đoạn, chẳng hạn so sánh giữa các tháng. Đây là cơ sở cho mọi KPI dựa trên thời lượng. Vì sao điều này quan trọng Dấu thời gian này rất quan trọng để sắp xếp sự kiện theo trình tự và tính mọi chỉ số thời gian, như thời gian xử lý và thời lượng, vốn là nền tảng của process mining. Lấy dữ liệu ở đâu Được lấy từ nhiều trường ngày giờ trong các bảng SAP, chẳng hạn Ngày tạo (BKPF-CPUDT), Ngày hạch toán (BKPF-BUDAT), Ngày tất toán (BSAK-AUGDT) hoặc dấu thời gian trong nhật ký thay đổi (CDHDR-UDATE/UTIME). Ví dụ 2023-10-01T09:00:00Z2023-10-05T14:30:15Z2023-10-15T11:21:05Z | |||
| Hệ thống nguồn SourceSystem | Hệ thống được dùng để trích xuất dữ liệu. | ||
| Mô tả Thuộc tính này xác định nguồn gốc của dữ liệu quy trình. Trong chế độ xem này, giá trị thường là 'SAP S/4HANA'. Trong môi trường có nhiều ERP hoặc hệ thống tích hợp, trường này rất quan trọng để theo dõi nguồn gốc và phân tách dữ liệu. Trường này giúp bảo đảm phân tích đúng tập dữ liệu và hỗ trợ tìm nguyên nhân vấn đề về chất lượng dữ liệu bằng cách truy ngược về nguồn. Vì sao điều này quan trọng Xác định nguồn gốc dữ liệu, rất quan trọng cho quản trị dữ liệu, xử lý sự cố và môi trường có nhiều hệ thống. Lấy dữ liệu ở đâu Đây thường là giá trị cố định được thêm trong quá trình trích xuất dữ liệu để ghi nhãn nguồn gốc của tập dữ liệu. Ví dụ SAP S/4HANASAP ECC 6.0S4H_PROD_100 | |||
| Lần cập nhật dữ liệu gần nhất LastDataUpdate | Dấu thời gian cho biết lần gần nhất dữ liệu của bản ghi này được làm mới từ hệ thống nguồn. | ||
| Mô tả Thuộc tính này cho biết ngày giờ trích xuất hoặc cập nhật dữ liệu gần nhất từ SAP S/4HANA. Đây là trường siêu dữ liệu quan trọng để biết dữ liệu đang phân tích mới đến mức nào. Thông tin này giúp người dùng biết dữ liệu phân tích quy trình được cập nhật đến thời điểm nào. Nhờ đó, bạn có thể dự kiến độ trễ dữ liệu, lên lịch làm mới và duy trì tính toàn vẹn của dữ liệu. Vì sao điều này quan trọng Cho biết dữ liệu mới đến mức nào, giúp người dùng biết phân tích quy trình đã được cập nhật gần đây hay chưa. Lấy dữ liệu ở đâu Giá trị này được tạo và ghi vào từng bản ghi khi trích xuất dữ liệu từ hệ thống nguồn. Ví dụ 2024-05-20T04:00:00Z2024-05-21T04:00:00Z | |||
| Mã công ty CompanyCode | Đơn vị tổ chức chịu trách nhiệm xử lý hóa đơn. | ||
| Mô tả Mã công ty là đơn vị tổ chức nhỏ nhất có thể lập một bộ tài khoản hoàn chỉnh, độc lập để báo cáo bên ngoài. Trong quy trình công nợ phải trả, đây là pháp nhân có nghĩa vụ thanh toán cho nhà cung cấp. Phân tích theo mã công ty giúp so sánh hiệu quả quy trình giữa các pháp nhân trong tổ chức. Qua đó, bạn có thể xác định bộ phận nào tuân theo quy trình chuẩn, bộ phận nào hoạt động hiệu quả hơn, có thời gian xử lý dài hơn hoặc tỷ lệ làm lại cao hơn. Vì sao điều này quan trọng Cho phép so sánh hiệu quả quy trình giữa các pháp nhân, giúp xác định vấn đề và cách làm hiệu quả riêng theo khu vực hoặc đơn vị kinh doanh. Lấy dữ liệu ở đâu Có trong các bảng phần đầu chứng từ, chủ yếu là BKPF-BUKRS đối với hóa đơn FI và RBKP-BUKRS đối với hóa đơn MM. Ví dụ 10001710US01DE01 | |||
| Ngày đến hạn thanh toán hóa đơn InvoiceDueDate | Ngày cuối cùng phải thanh toán hóa đơn cho nhà cung cấp. | ||
| Mô tả Ngày đến hạn thanh toán hóa đơn là hạn chót để thanh toán cho nhà cung cấp, tránh phí trả chậm và duy trì quan hệ tốt. Ngày này được tính dựa trên ngày cơ sở của hóa đơn và điều khoản thanh toán đã thỏa thuận với nhà cung cấp. Ngày này rất quan trọng đối với dashboard 'Tuân thủ thanh toán và thời gian quá hạn' và KPI 'Tỷ lệ thanh toán đúng hạn'. So sánh ngày đến hạn với ngày thanh toán thực tế giúp xác định khoản thanh toán được thực hiện đúng hạn, sớm hay trễ, từ đó thấy rõ tác động đến tài chính và quan hệ với nhà cung cấp. Vì sao điều này quan trọng Đây là yếu tố chính để phân tích thanh toán đúng hạn, giúp đo hiệu quả thanh toán và tác động của việc này đến quan hệ với nhà cung cấp cũng như phí trả chậm. Lấy dữ liệu ở đâu Ngày này thường được tính toán. Ngày đến hạn ròng nằm trong trường BSEG-NETDT. Bạn cũng có thể tính ngày này từ ngày cơ sở thanh toán (BSEG-ZFBDT) và điều khoản thanh toán (BSEG-ZTERM). Ví dụ 2023-10-312023-11-152024-01-10 | |||
| Số đơn đặt hàng PurchaseOrderNumber | Mã định danh duy nhất của đơn đặt hàng liên quan đến hóa đơn, nếu có. | ||
| Mô tả Thuộc tính này liên kết hóa đơn với đơn đặt hàng (PO) đã được phê duyệt trước. Số PO là cơ sở cho quy trình đối chiếu ba bên (PO, hóa đơn và phiếu nhận hàng). Đây là thuộc tính quan trọng để phân tích tuân thủ và hiệu quả. Thuộc tính được dùng để tính KPI 'Tỷ lệ hóa đơn không có đơn đặt hàng', qua đó đo mức độ tuân thủ chính sách mua sắm. Đây cũng là cơ sở cho dashboard 'Hiệu quả đối chiếu ba bên', giúp phân tích quy trình đối chiếu các hóa đơn có PO. Vì sao điều này quan trọng Rất quan trọng để phân tích hiệu quả đối chiếu ba bên và đo mức độ tuân thủ chính sách mua sắm bằng cách xác định các hóa đơn được xử lý mà không có PO. Lấy dữ liệu ở đâu Có trong các bảng dòng hóa đơn, chẳng hạn RSEG-EBELN (đối với hóa đơn MM) hoặc BSEG-EBELN (đối với hóa đơn FI). Ví dụ 45000012344500005678 | |||
| Số tiền hóa đơn InvoiceAmount | Tổng số tiền trước thuế của hóa đơn theo đơn vị tiền tệ gốc trên chứng từ. | ||
| Mô tả Đây là tổng giá trị hóa đơn do nhà cung cấp gửi, gồm chi phí hàng hóa hoặc dịch vụ, thuế và các khoản phí khác trước khi trừ khoản khấu trừ hoặc chiết khấu. Số tiền hóa đơn là thuộc tính tài chính quan trọng, được dùng trong nhiều loại phân tích. Thuộc tính này giúp ưu tiên hóa đơn giá trị cao, hiểu tác động tài chính của chậm trễ trong quy trình, chẳng hạn phí trả chậm của hóa đơn lớn, và phân nhóm quy trình, ví dụ: 'Hóa đơn giá trị cao có đi theo lộ trình phê duyệt khác không?'. Đây cũng là thông tin cần thiết để phát hiện các khoản thanh toán có thể bị trùng. Vì sao điều này quan trọng Cung cấp bối cảnh tài chính cho quy trình, giúp phân tích theo giá trị, ưu tiên hóa đơn giá trị cao và định lượng tác động tài chính. Lấy dữ liệu ở đâu Có trong các bảng như RBKP-RMWWR (Tổng số tiền hóa đơn trước thuế) đối với hóa đơn MM, hoặc được tính từ các dòng hàng trong BSEG (trường WRBTR) đối với hóa đơn FI. Ví dụ 1500.00250.7512345.50 | |||
| Tên người dùng UserName | Mã người dùng đã thực hiện hoạt động. | ||
| Mô tả Thuộc tính này ghi lại mã người dùng SAP chịu trách nhiệm thực hiện một hoạt động cụ thể, chẳng hạn hạch toán, phê duyệt hoặc tất toán hóa đơn. Thuộc tính liên kết các bước trong quy trình với từng người dùng. Phân tích theo tên người dùng giúp hiểu cách phân bổ khối lượng công việc, xác định người có hiệu suất cao và tìm người có thể cần được đào tạo thêm. Đây cũng là thông tin quan trọng để phân tích điểm nghẽn phê duyệt trên dashboard, vì giúp xác định người phê duyệt cụ thể đang gây chậm trễ. Vì sao điều này quan trọng Gắn hoạt động với từng người dùng, giúp phân tích hiệu suất, khối lượng công việc và mức độ tuân thủ chính sách phân tách nhiệm vụ. Lấy dữ liệu ở đâu Thường có trong các bảng phần đầu như BKPF-USNAM (Người nhập) hoặc bảng chứng từ thay đổi CDHDR-USERNAME (Người thay đổi). Ví dụ ABROWNJSMITHAP_AUTOMATION | |||
| Tên nhà cung cấp VendorName | Tên nhà cung cấp đã gửi hóa đơn. | ||
| Mô tả Thuộc tính này chứa tên chính thức của nhà cung cấp. Tên được liên kết qua Mã nhà cung cấp lưu trên chứng từ hóa đơn. Phân tích theo nhà cung cấp rất quan trọng để quản lý quan hệ và xác định vấn đề quy trình liên quan đến từng nhà cung cấp. Bạn có thể trả lời các câu hỏi như 'Nhà cung cấp nào gửi nhiều hóa đơn sai lệch nhất?' hoặc 'Chúng ta có thường xuyên thanh toán đúng hạn cho các nhà cung cấp chiến lược không?'. Cùng với số hóa đơn và số tiền, đây cũng là trường quan trọng để phát hiện các khoản thanh toán có thể bị trùng. Vì sao điều này quan trọng Cho phép phân tích hiệu quả quy trình theo nhà cung cấp, giúp xác định nhà cung cấp có vấn đề và quản lý hiệu quả quan hệ với các nhà cung cấp chiến lược. Lấy dữ liệu ở đâu Lấy từ bảng dữ liệu chủ nhà cung cấp LFA1 (trường NAME1), liên kết qua Mã nhà cung cấp (LIFNR) trong BKPF hoặc RBKP. Ví dụ Office Supplies Inc.Global Consulting GroupMachine Parts GmbH | |||
| Đã nhận chiết khấu DiscountTaken | Cờ đúng/sai cho biết chiết khấu thanh toán sớm đã được áp dụng hay chưa. | ||
| Mô tả Thuộc tính này cho biết khoản chiết khấu tiền mặt có thực sự được áp dụng khi thanh toán hóa đơn hay không. Đây là yếu tố quan trọng để đo lường hiệu quả tài chính của quy trình công nợ phải trả. Cờ này là cơ sở của KPI 'Tỷ lệ tận dụng chiết khấu thanh toán sớm'. Lọc các hóa đơn đủ điều kiện được chiết khấu theo điều khoản thanh toán, rồi phân tích cờ này, giúp doanh nghiệp tính chính xác số tiền đã tiết kiệm và số cơ hội tiết kiệm bị bỏ lỡ. Qua đó, bạn có thể đo lường rõ ràng hiệu quả xử lý công nợ phải trả. Vì sao điều này quan trọng Đo trực tiếp mức độ tận dụng chiết khấu thanh toán sớm, yếu tố ảnh hưởng trực tiếp đến lợi nhuận của công ty. Lấy dữ liệu ở đâu Được xác định bằng cách kiểm tra xem trường số tiền chiết khấu (BSEG-SKNTO) trên chứng từ thanh toán có lớn hơn 0 hay không. Ví dụ truefalse | |||
| Điều khoản thanh toán PaymentTerms | Các điều kiện thanh toán hóa đơn đã thỏa thuận với nhà cung cấp, thường bao gồm cơ hội được chiết khấu. | ||
| Mô tả Điều khoản thanh toán quy định hạn thanh toán và các khoản chiết khấu nếu thanh toán sớm. Ví dụ, điều khoản 'Z001' có thể có nghĩa là 'Thanh toán trong vòng 30 ngày, được chiết khấu 2% nếu thanh toán trong 10 ngày'. Thuộc tính này là cơ sở cho dashboard 'Tỷ lệ tận dụng chiết khấu thanh toán sớm'. Phân tích điều khoản thanh toán giúp xác định tất cả hóa đơn đủ điều kiện được chiết khấu. So sánh với khoản chiết khấu thực tế cho thấy cơ hội tiết kiệm bị bỏ lỡ và giúp đo lường hiệu quả của quy trình thanh toán. Vì sao điều này quan trọng Thuộc tính này rất cần thiết để phân tích cơ hội được chiết khấu khi thanh toán sớm, đo lường hiệu quả tài chính của quy trình thanh toán và xác định khoản tiết kiệm bị bỏ lỡ. Lấy dữ liệu ở đâu Có trong các dòng mục nhà cung cấp, bảng BSEG-ZTERM hoặc phần đầu hóa đơn tại RBKP-ZTERM. Ví dụ Z0010001NT30 | |||
| Được tự động hóa IsAutomated | Cờ cho biết hoạt động do hệ thống tự động thực hiện hay do người dùng thực hiện. | ||
| Mô tả Thuộc tính dạng đúng/sai này phân biệt hoạt động do người thực hiện với hoạt động do tác vụ hệ thống, workflow hoặc bot thực hiện. Ví dụ, đợt chạy thanh toán tự động hoặc thao tác hạch toán hóa đơn do hệ thống tạo sẽ được đánh dấu là tự động. Phân tích thuộc tính này giúp hiểu mức độ tự động hóa trong quy trình công nợ phải trả. Bạn có thể dùng thuộc tính để đo hiệu quả của các sáng kiến tự động hóa, so sánh hiệu quả giữa bước tự động và bước thủ công, đồng thời tìm thêm cơ hội tự động hóa. Vì sao điều này quan trọng Giúp đo mức độ tự động hóa trong quy trình, phân tích hiệu quả tự động hóa và xác định cơ hội cải thiện thêm. Lấy dữ liệu ở đâu Được suy ra từ Tên người dùng, chẳng hạn mã người dùng hệ thống như 'SAP_SYSTEM' hoặc 'BATCHUSER', hoặc từ mã giao dịch cụ thể gắn với tác vụ tự động. Ví dụ truefalse | |||
| Loại chứng từ hóa đơn InvoiceDocumentType | Phân loại chứng từ hóa đơn, quyết định cách chứng từ được xử lý trong SAP. | ||
| Mô tả Loại chứng từ là một thiết lập quan trọng trong SAP để phân loại chứng từ kế toán. Ví dụ, 'KR' thường dùng cho hóa đơn nhà cung cấp, 'RE' cho hóa đơn MM và 'KG' cho giấy báo có của nhà cung cấp. Loại chứng từ quyết định các yếu tố như dải số chứng từ và những trường bắt buộc. Trong phân tích quy trình, lọc theo Loại chứng từ giúp so sánh luồng xử lý của các loại hóa đơn khác nhau. Chẳng hạn, quy trình phê duyệt giấy báo có có thể khác với hóa đơn thông thường. Thông tin này hữu ích cho dashboard 'Các biến thể định tuyến phê duyệt hóa đơn'. Vì sao điều này quan trọng Cho phép phân nhóm quy trình theo cách xử lý từng loại hóa đơn, qua đó cho thấy sự khác biệt về lộ trình xử lý và thời gian hoàn tất. Lấy dữ liệu ở đâu Lấy trực tiếp từ trường BKPF-BLART trong bảng phần đầu chứng từ. Ví dụ KRREKG | |||
| Lý do chặn thanh toán BlockingReason | Lý do hóa đơn bị chặn thanh toán, cho biết có sai lệch cần xử lý. | ||
| Mô tả Nếu hóa đơn không vượt qua bước kiểm tra trong đối chiếu 3 bên hoặc các bước xác minh khác, hóa đơn sẽ bị chặn thanh toán. Lý do chặn thanh toán cho biết vấn đề cụ thể, chẳng hạn như sai lệch số lượng, chênh lệch giá hoặc thiếu phiếu nhận hàng. Thuộc tính này rất quan trọng đối với dashboard 'Phân tích xử lý lại hóa đơn sai lệch'. Phân tích tần suất của từng lý do chặn giúp xác định nguyên nhân gốc rễ gây kém hiệu quả trong quy trình. Ví dụ, nếu 'Chênh lệch giá' là lý do phổ biến, có thể dữ liệu chủ trong hệ thống mua hàng đang có vấn đề. Vì sao điều này quan trọng Giúp xác định trực tiếp nguyên nhân gốc rễ gây sai lệch và phải xử lý lại hóa đơn, từ đó tập trung cải tiến quy trình vào đúng vấn đề. Lấy dữ liệu ở đâu Được lưu trong các bảng dòng mục hóa đơn như RSEG, ở những trường bắt đầu bằng SPGR* (ví dụ: SPGRP, SPGRQ, SPGRT). Cũng có thể tìm thấy trong RBKP_BLOCKED. Ví dụ Sai lệch giáSai lệch số lượngThiếu phiếu nhận hàng | |||
| Ngày tất toán ClearingDate | Ngày thanh toán được thực hiện và hóa đơn được tất toán khỏi các khoản mục chưa thanh toán. | ||
| Mô tả Ngày tất toán cho biết hóa đơn đã được thanh toán xong. Đây là ngày diễn ra hoạt động 'Đã thanh toán', đánh dấu bước cuối trong hầu hết các trường hợp xử lý hóa đơn thành công. Ngày này được dùng để xác định ngày thanh toán thực tế và so sánh với hạn thanh toán hóa đơn. Vì vậy, đây là dữ liệu cần thiết để tính KPI 'Tỷ lệ thanh toán đúng hạn' và phân tích hiệu quả thanh toán. Ngày này cũng là mốc kết thúc để tính tổng thời gian xử lý hóa đơn từ đầu đến cuối. Vì sao điều này quan trọng Đánh dấu thời điểm hóa đơn được thanh toán xong, làm mốc kết thúc để tính thời gian xử lý và phân tích việc thanh toán đúng hạn. Lấy dữ liệu ở đâu Có trong các bảng mục đã tất toán, chẳng hạn như BSAK-AUGDT đối với nhà cung cấp. Ví dụ 2023-10-282023-11-142024-01-09 | |||
| Số hóa đơn của nhà cung cấp VendorInvoiceNumber | Số hóa đơn do nhà cung cấp ghi trên chứng từ. | ||
| Mô tả Đây là mã tham chiếu trong hệ thống kế toán của nhà cung cấp, được in trên hóa đơn giấy hoặc hóa đơn điện tử. Mã này được nhập thủ công hoặc ghi nhận bằng OCR khi nhận hóa đơn. Trường này rất quan trọng cho hoạt động hằng ngày và phân tích, đặc biệt là dashboard 'Khoản thanh toán hóa đơn trùng lặp tiềm ẩn'. Một cách phổ biến để phát hiện hóa đơn trùng là tìm các chứng từ hóa đơn nội bộ có cùng tên nhà cung cấp, số hóa đơn của nhà cung cấp và số tiền hóa đơn. Đây là mã tham chiếu bên ngoài chính của hóa đơn. Vì sao điều này quan trọng Đây là trường quan trọng để phát hiện các khoản thanh toán trùng lặp tiềm ẩn, đồng thời là mã tham chiếu bên ngoài chính khi trao đổi với nhà cung cấp. Lấy dữ liệu ở đâu Được lưu trong trường 'Reference' ở phần đầu chứng từ, thường là BKPF-XBLNR. Ví dụ INV-2023-9876733401120231015-001 | |||
| Thanh toán trễ IsLatePayment | Cờ đúng/sai cho biết hóa đơn có được thanh toán sau hạn hay không. | ||
| Mô tả Thuộc tính được tính toán này là cờ đúng/sai cho biết hóa đơn có được thanh toán sau hạn chính thức hay không. Giá trị được xác định bằng cách so sánh 'Ngày tất toán' với 'Hạn thanh toán hóa đơn'. Cờ này giúp đơn giản hóa việc phân tích trên dashboard 'Tuân thủ thanh toán và thời gian quá hạn' và KPI 'Tỷ lệ thanh toán đúng hạn'. Bạn có thể dễ dàng lọc và tổng hợp dữ liệu để đếm số khoản thanh toán trễ, tính tỷ lệ thanh toán đúng hạn và xác định nhà cung cấp hoặc mã công ty có tỷ lệ thanh toán trễ cao. Vì sao điều này quan trọng Đo trực tiếp mức độ tuân thủ điều khoản thanh toán, giúp tính KPI thanh toán đúng hạn và xác định những khâu có hiệu quả thanh toán thấp. Lấy dữ liệu ở đâu Thuộc tính được tính toán. Logic: IF ClearingDate > InvoiceDueDate THEN true ELSE false. Ví dụ truefalse | |||
| Tiền tệ của hóa đơn InvoiceCurrency | Mã tiền tệ dùng cho số tiền trên hóa đơn (ví dụ: USD, EUR). | ||
| Mô tả Thuộc tính này cho biết số tiền trên hóa đơn được tính bằng loại tiền tệ nào. Đây là thông tin cần thiết để hiểu các giá trị tài chính. Trong tổ chức hoạt động ở nhiều quốc gia, phân tích hóa đơn mà không xét đến tiền tệ có thể dẫn đến kết luận sai lệch. Trường này giúp xử lý dữ liệu tài chính phù hợp, bằng cách quy đổi mọi khoản tiền về một loại tiền tệ báo cáo hoặc phân tích riêng theo từng loại tiền tệ để hiểu hoạt động tài chính ở từng khu vực. Vì sao điều này quan trọng Cung cấp thông tin cần thiết về số tiền trên hóa đơn, giúp phân tích và lập báo cáo tài chính chính xác, nhất là khi hoạt động ở nhiều quốc gia. Lấy dữ liệu ở đâu Có trong các bảng phần đầu chứng từ, chủ yếu là BKPF-WAERS hoặc RBKP-WAERS. Ví dụ USDEURGBPJPY | |||
Các hoạt động trong quy trình xử lý hóa đơn phải trả
| Hoạt động | Mô tả | ||
|---|---|---|---|
| Chặn thanh toán hóa đơn | Hệ thống đã tự động chặn hóa đơn hoặc người dùng đã chặn thủ công, khiến hóa đơn không thể được thanh toán. Nguyên nhân thường là chênh lệch giá, số lượng hoặc thiếu phê duyệt. | ||
| Vì sao điều này quan trọng Đây là dấu hiệu quan trọng cho thấy có vấn đề và công việc phải làm lại. Phân tích lý do và thời gian chặn giúp tìm ra nguyên nhân gốc rễ gây chậm thanh toán và kém hiệu quả trong quy trình. Lấy dữ liệu ở đâu Trạng thái này được ghi rõ trong trường Mã chặn thanh toán (ZLSPR) trên dòng nhà cung cấp của chứng từ kế toán (bảng BSEG). Thu thập Được ghi nhận qua chứng từ thay đổi khi trường BSEG-ZLSPR có mã lý do chặn. Loại sự kiện explicit | |||
| Hạch toán hóa đơn | Hóa đơn được ghi nhận chính thức vào sổ cái, tạo ra một khoản nợ phải trả. Chứng từ tạm giữ được chuyển thành chứng từ đã hạch toán hoặc hóa đơn được hạch toán trực tiếp. | ||
| Vì sao điều này quan trọng Đây là cột mốc tài chính quan trọng. Sự kiện xác nhận nghĩa vụ thanh toán của công ty và thường là điều kiện cần để lên lịch thanh toán. Lấy dữ liệu ở đâu Sự kiện này được xác định bằng Ngày hạch toán (BUDAT) trong phần đầu chứng từ (BKPF). Chứng từ đã hạch toán có trạng thái (BKPF-BSTAT) để trống. Thu thập Dùng ngày hạch toán (BKPF-BUDAT) cho các chứng từ không bị tạm giữ (BKPF-BSTAT để trống). Loại sự kiện explicit | |||
| Hóa đơn được phê duyệt | Hóa đơn đã nhận đủ phê duyệt cần thiết trong hệ thống workflow. Đây thường là bước cuối trước khi hóa đơn được hạch toán hoặc bỏ chặn thanh toán. | ||
| Vì sao điều này quan trọng Cột mốc quan trọng này đánh dấu kết thúc chu kỳ phê duyệt. Thời gian từ lúc chuyển đi phê duyệt đến khi được duyệt là chỉ số quan trọng để đánh giá hiệu quả. Lấy dữ liệu ở đâu Được ghi nhận trong nhật ký SAP Business Workflow dưới dạng bước hoàn tất hoặc phê duyệt cuối cùng. Ngoài ra, có thể suy ra sự kiện này từ việc bỏ chặn thanh toán sau khi chuyển hóa đơn đi phê duyệt. Thu thập Trích xuất sự kiện hoàn tất workflow từ nhật ký SAP workflow hoặc xác định sự kiện 'phê duyệt cuối cùng'. Loại sự kiện explicit | |||
| Hủy hóa đơn | Chứng từ hóa đơn đã được đảo, qua đó xóa bỏ ảnh hưởng tài chính của chứng từ. Đây là trạng thái kết thúc thay thế của quy trình, thường do nhập sai hoặc tranh chấp với nhà cung cấp. | ||
| Vì sao điều này quan trọng Theo dõi các lần hủy giúp xác định nguyên nhân khiến quy trình thất bại, chẳng hạn gửi trùng hoặc dữ liệu hóa đơn không chính xác. Những nguyên nhân này có thể bắt nguồn từ các bước trước đó. Lấy dữ liệu ở đâu Sự kiện này được ghi nhận rõ khi tạo chứng từ đảo. Phần đầu chứng từ gốc (BKPF) sẽ có số chứng từ đảo (STBLG) và lý do đảo. Thu thập Xác định ngày hạch toán của chứng từ đảo, được liên kết trong phần đầu chứng từ gốc (BKPF-STBLG). Loại sự kiện explicit | |||
| Nhận hóa đơn | Hoạt động này ghi nhận thời điểm tạo chứng từ hóa đơn trong SAP, bằng cách nhập thủ công hoặc qua giao diện tự động như OCR/VIM. Sự kiện thường được xác định từ ngày và giờ tạo phần đầu chứng từ kế toán. | ||
| Vì sao điều này quan trọng Là điểm bắt đầu của quy trình, hoạt động này cần thiết để tính thời gian xử lý hóa đơn từ đầu đến cuối và đo thông lượng của toàn bộ quy trình công nợ phải trả. Lấy dữ liệu ở đâu Sự kiện này được lấy từ bảng phần đầu chứng từ kế toán (BKPF), dựa trên ngày tạo chứng từ (CPUDT) và giờ tạo (CPUTM). Thu thập Dùng dấu thời gian tạo chứng từ hóa đơn (BKPF-CPUDT, BKPF-CPUTM). Loại sự kiện explicit | |||
| Tất toán thanh toán | Hoạt động này đánh dấu thời điểm hóa đơn được đóng hoàn toàn, khi khoản thanh toán và hóa đơn được đối chiếu với nhau trong sổ phụ. Đây là dấu hiệu quy trình đã hoàn tất. | ||
| Vì sao điều này quan trọng Là điểm kết thúc chính thức của quy trình, hoạt động này cần thiết để tính chính xác thời gian xử lý từ đầu đến cuối. Hoạt động xác nhận khoản nợ đã được thanh toán. Lấy dữ liệu ở đâu Đây là sự kiện được ghi nhận rõ khi trường Ngày tất toán (AUGDT) có giá trị trên dòng nhà cung cấp của chứng từ hóa đơn (bảng BSEG). Thu thập Dùng ngày tất toán (BSEG-AUGDT) trên dòng hóa đơn. Loại sự kiện explicit | |||
| Thực hiện thanh toán | Hóa đơn đã được thanh toán. Sự kiện được ghi nhận khi đợt chạy thanh toán hoàn tất và chứng từ thanh toán được tạo, hạch toán. | ||
| Vì sao điều này quan trọng Hoạt động này rất quan trọng để phân tích dòng tiền và đo KPI 'Tỷ lệ thanh toán đúng hạn' bằng cách so sánh ngày thanh toán với ngày đến hạn của hóa đơn. Lấy dữ liệu ở đâu Sự kiện này được lấy từ ngày hạch toán của chứng từ thanh toán dùng để tất toán hóa đơn. Số chứng từ thanh toán được liên kết trong trường chứng từ tất toán (AUGBL) trên dòng hóa đơn (BSEG). Thu thập Xác định ngày hạch toán (BUDAT) của chứng từ thanh toán dùng để tất toán dòng hóa đơn. Loại sự kiện explicit | |||
| Chuyển hóa đơn đi phê duyệt | Hóa đơn đã được đưa vào workflow để xin các phê duyệt cần thiết theo quy tắc kinh doanh. Đây là thời điểm bắt đầu quy trình con phê duyệt. | ||
| Vì sao điều này quan trọng Hoạt động này là điểm bắt đầu để đo KPI 'Thời gian phê duyệt hóa đơn trung bình' và phân tích điểm nghẽn trong khâu phê duyệt. Lấy dữ liệu ở đâu Có thể lấy dữ liệu từ nhật ký SAP Business Workflow (các bảng SWW*), nơi ghi nhận thời điểm bắt đầu một phiên bản workflow liên kết với đối tượng hóa đơn, chẳng hạn BUS2081. Thu thập Trích xuất sự kiện bắt đầu workflow từ nhật ký SAP workflow, chẳng hạn bảng SWW_WIHEAD, được liên kết với chứng từ hóa đơn. Loại sự kiện explicit | |||
| Đã quá ngày đến hạn thanh toán hóa đơn | Sự kiện được tính toán để cho biết ngày đến hạn ròng của hóa đơn đã qua nhưng hóa đơn chưa được thanh toán. Điều này cho thấy khoản thanh toán bị trễ hoặc quá hạn. | ||
| Vì sao điều này quan trọng Hoạt động này rất cần thiết cho dashboard 'Tuân thủ thanh toán và thời gian quá hạn'. Hoạt động giúp chủ động xác định, quản lý hóa đơn quá hạn và phân tích nguyên nhân gốc rễ gây chậm thanh toán. Lấy dữ liệu ở đâu SAP không ghi nhận sự kiện này trực tiếp. Sự kiện được tính bằng cách so sánh ngày hiện tại của hệ thống với ngày đến hạn ròng, được tính từ BSEG-ZFBDT hoặc ngày cơ sở cùng điều khoản thanh toán. Thu thập Sự kiện được tính toán và kích hoạt khi dấu thời gian của sự kiện muộn hơn ngày đến hạn ròng của hóa đơn. Loại sự kiện calculated | |||
| Đã xử lý sai lệch | Hoạt động này cho biết vấn đề đã được phát hiện trước đó, có thể là nguyên nhân gây chặn thanh toán, đã được kiểm tra và xử lý. Sự kiện được ghi nhận khi bỏ chặn thanh toán hóa đơn. | ||
| Vì sao điều này quan trọng Theo dõi vòng lặp làm lại này rất quan trọng đối với dashboard 'Phân tích công việc làm lại do sai lệch hóa đơn'. Việc này giúp định lượng thời gian và công sức dành cho sửa lỗi. Lấy dữ liệu ở đâu Sự kiện này được suy ra từ chứng từ thay đổi cho thấy đã bỏ chặn thanh toán. Nhật ký thay đổi của trường BSEG-ZLSPR là nguồn dữ liệu chính. Thu thập Tìm các chứng từ thay đổi của bảng BSEG, trong đó giá trị trường ZLSPR được đổi từ có giá trị thành để trống. Loại sự kiện inferred | |||
| Đối chiếu với đơn đặt hàng | Hoạt động này cho biết hóa đơn đã được đối chiếu thành công với đơn đặt hàng tương ứng. Đây là bước quan trọng trong quy trình đối chiếu ba bên đối với hóa đơn mua hàng. | ||
| Vì sao điều này quan trọng Phân tích hoạt động này giúp đo hiệu quả đối chiếu và là cơ sở cho KPI 'Hiệu quả đối chiếu ba bên' và 'Tỷ lệ hóa đơn không có đơn đặt hàng'. Lấy dữ liệu ở đâu Sự kiện này được suy ra khi một dòng hóa đơn trong bảng BSEG hoặc ACDOCA có số đơn đặt hàng (EBELN) và số dòng hàng (EBELP) hợp lệ. Thu thập Được suy ra từ tham chiếu đơn đặt hàng (BSEG-EBELN) trên chứng từ hóa đơn khi chứng từ được tạo. Loại sự kiện inferred | |||
| Đối chiếu với phiếu nhận hàng | Hoạt động này cho biết số lượng và giá trị trên hóa đơn đã được đối chiếu thành công với phiếu nhận hàng tương ứng. Đây là bước kiểm tra cuối cùng trong quy trình đối chiếu ba bên. | ||
| Vì sao điều này quan trọng Theo dõi hoạt động này giúp xác định điểm kém hiệu quả trong quy trình đối chiếu ba bên và phát hiện chênh lệch giữa hàng đã nhận với hàng nhà cung cấp lập hóa đơn. Lấy dữ liệu ở đâu Sự kiện này được suy ra từ tham chiếu chứng từ vật tư (phiếu nhận hàng) trên dòng hóa đơn, thường được liên kết qua lịch sử dòng hàng của đơn đặt hàng. Thu thập Được suy ra từ tham chiếu phiếu nhận hàng trên dòng hóa đơn, chẳng hạn trong RSEG đối với hóa đơn MIRO. Loại sự kiện inferred | |||
| Hóa đơn bị từ chối | Người phê duyệt đã từ chối hóa đơn trong workflow phê duyệt. Thông thường, hóa đơn sẽ được gửi lại cho người xử lý để sửa hoặc bổ sung thông tin. | ||
| Vì sao điều này quan trọng Theo dõi các lần từ chối giúp phát hiện vòng lặp làm lại trong quy trình phê duyệt, đồng thời có thể cho thấy vấn đề về tuân thủ chính sách hoặc mã hóa hóa đơn không chính xác. Lấy dữ liệu ở đâu Sự kiện này được ghi nhận dưới dạng kết quả cụ thể trong nhật ký SAP Business Workflow liên kết với hóa đơn. Thu thập Trích xuất sự kiện có trạng thái 'bị từ chối' từ nhật ký SAP workflow. Loại sự kiện explicit | |||
| Tạm giữ hóa đơn | Hóa đơn đã được nhập vào hệ thống nhưng chưa hạch toán vào sổ cái. Đây thường là bước có chủ đích để lưu chứng từ chưa hoàn chỉnh, chờ xử lý hoặc phê duyệt sau. | ||
| Vì sao điều này quan trọng Theo dõi hóa đơn tạm giữ giúp phát hiện chậm trễ trước khi bắt đầu hạch toán chính thức, đồng thời chỉ ra vấn đề về dữ liệu chưa đầy đủ hoặc khâu kiểm tra ban đầu. Lấy dữ liệu ở đâu Trạng thái này được xác định từ trường trạng thái chứng từ trong phần đầu chứng từ kế toán (BKPF-BSTAT = 'V' nghĩa là tạm giữ). Sự kiện xảy ra khi trạng thái được thiết lập. Thu thập Tìm các chứng từ thay đổi của bảng BKPF, trong đó trường BSTAT được đặt thành 'V' (Vor-erfasst/nhập trước). Loại sự kiện inferred | |||
| Tạo đề xuất thanh toán | Hóa đơn đã được đưa vào đề xuất thanh toán trong một đợt chạy thanh toán, chẳng hạn F110. Hóa đơn đã được lên lịch thanh toán, chờ đợt chạy được thực hiện chính thức. | ||
| Vì sao điều này quan trọng Hoạt động này cho thấy khoản nợ phải trả đang mở đã chuyển sang giai đoạn chuẩn bị thanh toán, giúp phân tích hiệu quả vận hành thanh toán. Lấy dữ liệu ở đâu Sự kiện này được ghi rõ trong các bảng dữ liệu đợt chạy thanh toán, cụ thể là REGUP (các khoản mục được chương trình thanh toán xử lý) và REGUH (phần đầu). Thu thập Xác định thời điểm hóa đơn xuất hiện trong bảng REGUP thuộc đợt chạy thanh toán được ghi nhận trong REGUH. Loại sự kiện explicit | |||
Hướng dẫn trích xuất dữ liệu
Các bước
- Điều kiện tiên quyết và quyền truy cập: Đảm bảo bạn có người dùng được cấp quyền đọc lược đồ cơ sở dữ liệu SAP S/4HANA (thường là SAPABAP1 hoặc lược đồ tương tự), nơi lưu các CDS view. Bạn cần một công cụ SQL có thể kết nối với cơ sở dữ liệu SAP HANA, chẳng hạn như SAP HANA Studio, DBeaver hoặc công cụ truy vấn cơ sở dữ liệu tương tự.
- Xác định các CDS view chính: Các CDS view chính cần trích xuất gồm I_JournalEntry, I_JournalEntryItem, I_SupplierInvoiceAPI01, I_ChangeDocument, I_WorkflowStatusDetails và I_PaymentProposalItem. Tìm hiểu các trường quan trọng trong những view này.
- Xác định phạm vi truy vấn: Mở công cụ SQL và kết nối với cơ sở dữ liệu SAP HANA. Trước khi chạy truy vấn đầy đủ, hãy xác định phạm vi trích xuất: đặt đúng mã hệ thống nguồn, khoảng ngày của hóa đơn (CreationDateTime) và các Company Code cần lấy.
- Chuẩn bị truy vấn chính: Sao chép toàn bộ truy vấn SQL trong phần truy vấn vào công cụ SQL. Truy vấn dùng Common Table Expressions (CTE) để chọn tập hóa đơn ban đầu, sau đó tạo nhật ký sự kiện bằng cách hợp nhất dữ liệu của 15 hoạt động khác nhau.
- Đặt tham số truy vấn: Tìm các biến giữ chỗ trong truy vấn SQL đã sao chép. Thay '[YYYY-MM-DD]' bằng ngày bắt đầu và ngày kết thúc của kỳ phân tích. Thay '[Your Company Code 1]', '[Your Company Code 2]' bằng danh sách SAP Company Code bạn muốn phân tích.
- Chạy truy vấn trích xuất: Chạy toàn bộ truy vấn SQL. Tùy vào lượng dữ liệu và khoảng ngày đã chọn, quá trình có thể mất từ vài phút đến vài giờ.
- Kiểm tra kết quả ban đầu: Khi truy vấn chạy xong, xem vài trăm dòng đầu tiên. Kiểm tra tính nhất quán của dữ liệu, xác nhận các cột có dữ liệu như dự kiến và đảm bảo có nhiều giá trị ActivityName khác nhau.
- Xuất nhật ký sự kiện: Xuất toàn bộ kết quả từ công cụ SQL sang tệp CSV. Đảm bảo tệp dùng mã hóa UTF-8 để tránh lỗi ký tự. Đặt tên tệp dễ nhận biết, chẳng hạn sap_s4hana_ap_event_log.csv.
- Chuẩn bị tải lên: Trước khi tải lên công cụ process mining, hãy xác nhận tiêu đề cột trong tệp CSV khớp chính xác với tên thuộc tính bắt buộc: Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName, v.v.
- Tải lên công cụ process mining: Tải tệp CSV đã tạo lên nền tảng process mining, rồi ánh xạ các cột vào trường mã hồ sơ, hoạt động và dấu thời gian tương ứng.
Cấu hình
- CDS view chính: Quá trình trích xuất kết hợp các CDS View tiêu chuẩn của S/4HANA. Các view chính gồm:
- I_JournalEntry và I_JournalEntryItem: Lấy thông tin tiêu đề và mục chứng từ tài chính, chi tiết hạch toán và thông tin tất toán.
- I_SupplierInvoiceAPI01: Lấy thông tin riêng của hóa đơn MM (Logistics), bao gồm tham chiếu PO và chặn thanh toán.
- I_ChangeDocument: Theo dõi chính xác thời điểm thay đổi, chẳng hạn khi đặt hoặc gỡ chặn thanh toán.
- I_WorkflowStatusDetails: Trích xuất các sự kiện liên quan đến workflow phê duyệt hóa đơn.
- I_PaymentProposalItem: Xác định thời điểm hóa đơn được đưa vào đề xuất chạy thanh toán.
- I_Supplier: Bổ sung thông tin nhà cung cấp, chẳng hạn VendorName.
- Lọc theo khoảng ngày: Cần lọc theo khoảng ngày để giới hạn lượng dữ liệu. Truy vấn mẫu lọc theo CreationDateTime trong CTE Invoices_Base. Với lần phân tích đầu tiên, nên chọn khoảng 3-6 tháng để hiệu năng ở mức phù hợp.
- Bộ lọc bắt buộc: Luôn lọc theo CompanyCode. Phân tích cùng lúc dữ liệu của tất cả mã công ty có thể rất chậm và không phù hợp với nhu cầu kinh doanh. Đồng thời, lọc theo JournalEntryType để chỉ lấy chứng từ liên quan đến nhà cung cấp, chẳng hạn 'KR', 'RE'.
- Điều kiện tiên quyết: Người dùng cơ sở dữ liệu chạy truy vấn phải có quyền SELECT trên tất cả CDS view được dùng và trên lược đồ HANA bên dưới. Quyền truy cập ở cấp ứng dụng trong SAP GUI là chưa đủ.
- Lưu ý về hiệu năng: Truy vấn trực tiếp I_ChangeDocument có thể tiêu tốn nhiều tài nguyên. Truy vấn mẫu giảm tải bằng cách lọc hóa đơn trước. Với tập dữ liệu rất lớn, hãy chạy trích xuất ngoài giờ cao điểm hoặc chia thành các đợt theo khoảng ngày nhỏ hơn.
Truy vấn mẫu sql
-- Common Table Expression (CTE) to select the base set of AP Invoices
WITH Invoices_Base AS (
SELECT
I_JournalEntry.CompanyCode,
I_JournalEntry.AccountingDocument,
I_JournalEntry.FiscalYear,
CONCAT(I_JournalEntry.CompanyCode, CONCAT(I_JournalEntry.AccountingDocument, I_JournalEntry.FiscalYear)) AS InvoiceId,
I_JournalEntry.CreationDateTime,
I_JournalEntry.CreatedByUser,
I_JournalEntry.DocumentStatus,
I_JournalEntry.JournalEntryType,
I_JournalEntry.ReversalReferenceJournalEntry,
I_JournalEntry.IsReversed,
I_JournalEntry.ReversalDate,
IJE_ITEM.NetDueDate,
IJE_ITEM.Supplier,
SUP.SupplierName AS VendorName,
IJE_ITEM.AmountInCompanyCodeCurrency AS InvoiceAmount,
MM.PurchaseOrder AS PurchaseOrderNumber,
MM.PaymentBlockingReason
FROM I_JournalEntry
-- Join to get item details like due date and supplier
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON I_JournalEntry.CompanyCode = IJE_ITEM.CompanyCode
AND I_JournalEntry.AccountingDocument = IJE_ITEM.AccountingDocument
AND I_JournalEntry.FiscalYear = IJE_ITEM.FiscalYear
AND IJE_ITEM.IsSupplier = 'X'
-- Join to get vendor name from master data
LEFT JOIN I_Supplier AS SUP
ON IJE_ITEM.Supplier = SUP.Supplier
-- Join to get MM Invoice specific data like PO Number and Payment Block
LEFT JOIN I_SupplierInvoiceAPI01 AS MM
ON I_JournalEntry.AccountingDocument = MM.AccountingDocument
AND I_JournalEntry.CompanyCode = MM.CompanyCode
AND I_JournalEntry.FiscalYear = MM.FiscalYear
WHERE
I_JournalEntry.JournalEntryType IN ('KR', 'RE') -- Standard Vendor Invoice Types
AND I_JournalEntry.CompanyCode IN ('[Your Company Code 1]', '[Your Company Code 2]')
AND I_JournalEntry.CreationDateTime BETWEEN '[YYYY-MM-DD]T00:00:00Z' AND '[YYYY-MM-DD]T23:59:59Z'
)
-- Event: 1. Invoice Received
SELECT
B.InvoiceId AS "Invoice",
'Invoice Received' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
UNION ALL
-- Event: 2. Invoice Parked
SELECT
B.InvoiceId AS "Invoice",
'Invoice Parked' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.DocumentStatus = 'V' -- 'V' stands for Parked
UNION ALL
-- Event: 3. Purchase Order Matched
SELECT
B.InvoiceId AS "Invoice",
'Purchase Order Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PurchaseOrderNumber IS NOT NULL AND B.PurchaseOrderNumber <> ''
UNION ALL
-- Event: 4. Goods Receipt Matched
SELECT
B.InvoiceId AS "Invoice",
'Goods Receipt Matched' AS "ActivityName",
B.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_SupplierInvoiceItemAPI01 AS MM_ITEM
ON B.AccountingDocument = MM_ITEM.AccountingDocument
AND B.FiscalYear = MM_ITEM.FiscalYear
WHERE MM_ITEM.GoodsReceipt IS NOT NULL AND MM_ITEM.GoodsReceipt <> ''
UNION ALL
-- Event: 5. Invoice Blocked For Payment
SELECT
B.InvoiceId AS "Invoice",
'Invoice Blocked For Payment' AS "ActivityName",
B.CreationDateTime AS "EventTime", -- Approximates block time as creation time if blocked on entry
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.PaymentBlockingReason IS NOT NULL AND B.PaymentBlockingReason <> ''
UNION ALL
-- Event: 6. Discrepancy Resolved (Payment Block Removed)
SELECT
B.InvoiceId AS "Invoice",
'Discrepancy Resolved' AS "ActivityName",
CD.ChangeTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CD.UserName AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_ChangeDocument AS CD
ON CONCAT(B.CompanyCode, B.AccountingDocument, B.FiscalYear) = CD.ObjectValue
WHERE CD.ChangeDocumentObject = 'INVOICE'
AND CD.TableName = 'RBKP'
AND CD.FieldName = 'ZLSPR' -- Field for Payment Block
AND CD.NewFieldValue = '' -- Block was removed
UNION ALL
-- Event: 7, 8, 9. Workflow Events (Routed, Approved, Rejected)
SELECT
B.InvoiceId AS "Invoice",
CASE WF.WorkflowStatus
WHEN 'READY' THEN 'Invoice Routed For Approval'
WHEN 'APPROVED' THEN 'Invoice Approved'
WHEN 'REJECTED' THEN 'Invoice Rejected'
END AS "ActivityName",
WF.WorkflowStatusChangedDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
WF.WorkflowStatusChangedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_WorkflowStatusDetails AS WF
ON B.InvoiceId = WF.WorkflowScenarioInstance
WHERE WF.WorkflowStatus IN ('READY', 'APPROVED', 'REJECTED')
UNION ALL
-- Event: 10. Invoice Posted
SELECT
B.InvoiceId AS "Invoice",
'Invoice Posted' AS "ActivityName",
JE.PostingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntry AS JE
ON B.AccountingDocument = JE.AccountingDocument
AND B.CompanyCode = JE.CompanyCode
AND B.FiscalYear = JE.FiscalYear
WHERE B.DocumentStatus <> 'V' -- Any status other than Parked is considered Posted for AP
UNION ALL
-- Event: 11. Payment Proposal Created
SELECT
B.InvoiceId AS "Invoice",
'Payment Proposal Created' AS "ActivityName",
PPI.PaymentProposalRunDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
PPI.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_PaymentProposalItem AS PPI
ON B.CompanyCode = PPI.CompanyCode
AND B.AccountingDocument = PPI.AccountingDocument
AND B.FiscalYear = PPI.FiscalYear
UNION ALL
-- Event: 12. Payment Executed
-- This links the invoice to its clearing document, which is the payment document
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Executed' AS "ActivityName",
CLEAR_JE.CreationDateTime AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
CLEAR_JE.CreatedByUser AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
INNER JOIN I_JournalEntry AS CLEAR_JE
ON IJE_ITEM.ClearingJournalEntry = CLEAR_JE.AccountingDocument
AND IJE_ITEM.CompanyCode = CLEAR_JE.CompanyCode
WHERE IJE_ITEM.ClearingJournalEntry IS NOT NULL AND IJE_ITEM.ClearingJournalEntry <> ''
AND CLEAR_JE.JournalEntryType = 'KZ' -- Vendor Payment Document Type
UNION ALL
-- Event: 13. Invoice Due Date Passed
SELECT
B.InvoiceId AS "Invoice",
'Invoice Due Date Passed' AS "ActivityName",
ADD_DAYS(B.NetDueDate, 1) AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
'SYSTEM' AS "UserName",
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
LEFT JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE B.NetDueDate < CURRENT_DATE
AND IJE_ITEM.ClearingDate IS NULL -- Invoice is not yet cleared
UNION ALL
-- Event: 14. Payment Cleared
SELECT DISTINCT
B.InvoiceId AS "Invoice",
'Payment Cleared' AS "ActivityName",
IJE_ITEM.ClearingDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
IJE_ITEM.ChangedByUser AS "UserName", -- User who cleared it
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
INNER JOIN I_JournalEntryItem AS IJE_ITEM
ON B.CompanyCode = IJE_ITEM.CompanyCode
AND B.AccountingDocument = IJE_ITEM.AccountingDocument
AND B.FiscalYear = IJE_ITEM.FiscalYear
WHERE IJE_ITEM.ClearingDate IS NOT NULL
UNION ALL
-- Event: 15. Invoice Cancelled
SELECT
B.InvoiceId AS "Invoice",
'Invoice Cancelled' AS "ActivityName",
B.ReversalDate AS "EventTime",
'SAP_S4HANA' AS "SourceSystem",
CURRENT_UTCTIMESTAMP AS "LastDataUpdate",
B.CreatedByUser AS "UserName", -- User who created the original document
B.CompanyCode AS "CompanyCode",
B.VendorName AS "VendorName",
B.InvoiceAmount AS "InvoiceAmount",
B.PurchaseOrderNumber AS "PurchaseOrderNumber",
B.NetDueDate AS "InvoiceDueDate"
FROM Invoices_Base B
WHERE B.IsReversed = 'X'; Các bước
- Xác nhận bạn có quyền đọc trực tiếp lược đồ SAP HANA chứa các bảng SAP S/4HANA liên quan. Lấy chuỗi kết nối, thông tin đăng nhập, tên lược đồ và quyền cần thiết để đọc BKPF, ACDOCA cùng các bảng bổ sung được cấu hình cho chứng từ tạm giữ, workflow, mua hàng, nhận hàng, đề xuất thanh toán, tất toán và dữ liệu đảo chứng từ.
- Xác nhận mô hình dữ liệu kỹ thuật trong hệ thống đích trước khi chạy. Kiểm tra tên vật lý, trường khóa, trường dấu thời gian, quan hệ đảo chứng từ, quan hệ thanh toán và cách hệ thống lưu dữ liệu workflow. Thay từng phần giữ chỗ trong ngoặc vuông của truy vấn bằng đối tượng hoặc trường tương ứng trong hệ thống. Không mặc định rằng dữ liệu workflow hoặc chứng từ tạm giữ được lưu trong một bảng dùng chung.
- Cấu hình tham số trích xuất. Đặt [Start date], [End date], [Company code filter], [Document type filter] và [Schema name]. Ban đầu, dùng khoảng ngày từ ba đến sáu tháng, sau đó mở rộng khi đã xác nhận hiệu năng và độ đầy đủ của dữ liệu.
- Chạy truy vấn SQL trong công cụ SQL SAP HANA được phê duyệt, chẳng hạn SAP HANA Database Explorer hoặc công cụ thực thi SQL được cấp quyền khác. Truy vấn xuất một dòng cho mỗi hoạt động được trích xuất rõ ràng, không dựa vào ProcessMind để suy ra sự kiện.
- Kiểm tra tập kết quả. Xác nhận Invoice là mã hồ sơ, ActivityName có đủ 15 tên hoạt động bắt buộc, EventTime có dữ liệu và trình tự thời gian hợp lý, SourceSystem nhận diện SAP S/4HANA, còn LastDataUpdate chứa dấu thời gian làm mới dữ liệu sau khi trích xuất. Kiểm tra sự kiện trùng lặp, quan hệ đảo chứng từ và các phép nối chứng từ trước khi nạp dữ liệu.
- Áp dụng các ánh xạ riêng của hệ thống nếu cần. Ví dụ: ánh xạ nguồn chứng từ tạm giữ đã cấu hình sang Invoice Parked; ánh xạ nguồn workflow đã cấu hình sang Invoice Routed For Approval, Invoice Approved và Invoice Rejected; ánh xạ nguồn thanh toán đã cấu hình sang Payment Proposal Created và Payment Executed. Nếu cần kiểm tra, hãy giữ mã định danh nguồn trong các cột bổ sung.
- Xuất kết quả thành tệp phân tách bằng dấu phân cách hoặc tập kết quả cơ sở dữ liệu, mỗi dòng là một sự kiện. Dùng mã hóa UTF-8, giữ dấu thời gian theo cùng một múi giờ, giữ nguyên chính xác tên các cột Invoice, ActivityName, EventTime, SourceSystem, LastDataUpdate, UserName, CompanyCode, VendorName, InvoiceAmount, PurchaseOrderNumber và InvoiceDueDate, đồng thời không gộp các hoạt động theo hóa đơn.
- Tải nhật ký sự kiện lên ProcessMind và đặt Invoice làm mã hồ sơ, ActivityName làm cột hoạt động, EventTime làm cột thời gian sự kiện. Xác nhận các thuộc tính tùy chọn được ánh xạ vào đúng trường. ProcessMind đọc nguyên trạng nhật ký sự kiện, vì vậy hãy đảm bảo mọi hoạt động cần trực quan hóa đã có thành từng dòng trước khi tải lên.
Cấu hình
- Khoảng ngày: Bắt đầu với khoảng từ ba đến sáu tháng. Tùy hoạt động được trích xuất, hãy dùng ngày hạch toán, ngày tạo chứng từ hoặc ngày sự kiện liên quan trong hệ thống nguồn. Chỉ mở rộng khoảng ngày sau khi đã kiểm tra thời gian chạy truy vấn và thời hạn lưu dữ liệu nguồn.
- Lọc theo công ty: Cấu hình [Company code filter] để giới hạn trích xuất vào các mã công ty cần thiết. Nếu không cần giới hạn, hãy chọn có kiểm soát tất cả công ty thay vì chạy truy vấn không giới hạn trên môi trường sản xuất.
- Lọc chứng từ: Chỉ cấu hình [Document type filter] sau khi xác nhận các loại chứng từ dùng cho hóa đơn nhà cung cấp, giấy báo có, chứng từ tạm giữ, chứng từ thanh toán và chứng từ đảo trong hệ thống đích.
- Ánh xạ lược đồ và đối tượng: Thay [Schema name] và mọi đối tượng hoặc trường nguồn trong ngoặc vuông bằng giá trị đã xác minh trong hệ thống SAP S/4HANA đích. Cần điều chỉnh truy vấn HANA trực tiếp theo các ứng dụng đã kích hoạt, phần mở rộng, thiết kế workflow và mô hình dữ liệu của hệ thống.
- Xử lý dấu thời gian: Chuẩn hóa tất cả dấu thời gian nguồn về cùng một múi giờ. Nếu chỉ có ngày, hãy dùng giờ mặc định đã được ghi lại và nêu rõ giới hạn này trong từ điển dữ liệu.
- Ý nghĩa sự kiện: Trích xuất mỗi hoạt động thành một dòng riêng. Không gộp nhiều hoạt động vào một bản ghi hóa đơn và không chờ ProcessMind tự tạo sự kiện đối chiếu, phê duyệt, đến hạn hoặc tất toán.
- Sự kiện đến hạn thanh toán: Chỉ tạo Invoice Due Date Passed cho hóa đơn có ngày đến hạn trước thời điểm đánh giá đã cấu hình và chưa có sự kiện tất toán tính đến thời điểm đó. Truy vấn dùng [Evaluation timestamp] để tính toán.
- Hiệu năng: Giới hạn khoảng thời gian và phạm vi công ty ban đầu, lọc theo các trường có chỉ mục hoặc liên quan đến phân vùng, tránh lấy các cột rộng không cần thiết và chạy trong khung giờ báo cáo được phê duyệt. Cân nhắc đưa các tập dữ liệu nguồn vào khu vực trung gian nếu truy vấn môi trường sản xuất vượt quá thời gian chạy đã thống nhất.
- Chiến lược làm mới: Đặt LastDataUpdate thành dấu thời gian chạy trích xuất. Với tải dữ liệu tăng dần, hãy lưu mốc thời gian dựa trên dấu thời gian thay đổi phù hợp ở nguồn và thêm khoảng thời gian truy xuất lùi để lấy các cập nhật đến muộn và sự kiện đảo chứng từ.
- Điều kiện tiên quyết: Cần có quyền cơ sở dữ liệu, quyền truy cập môi trường sản xuất đã được phê duyệt, hiểu biết về cấu hình Universal Journal của hệ thống, quyền truy cập vào các nguồn chứng từ tạm giữ, mua hàng, nhận hàng, workflow, thanh toán, tất toán và đảo chứng từ đã cấu hình, cùng các phê duyệt về giấy phép SAP hoặc quản trị dữ liệu nếu áp dụng.
Truy vấn mẫu sql
WITH
params AS (
SELECT
TO_DATE('[Start date]') AS start_date,
TO_DATE('[End date]') AS end_date,
TO_TIMESTAMP('[Evaluation timestamp]') AS evaluation_ts,
TO_TIMESTAMP('[Extraction timestamp]') AS extraction_ts
FROM DUMMY
),
base_invoice AS (
SELECT
b.mandt,
b.bukrs,
b.belnr,
b.gjahr,
b.bldat,
b.budat,
b.cpudt,
b.cputm,
b.usnam,
b.blart,
b.xblnr,
b.stblg,
b.stjah,
a.lifnr,
a.wrbtr,
a.waers,
a.zfbdt,
a.zbd1t,
a.zbd2t,
a.zbd3t,
a.ebeln,
a.ebelp,
a.augbl,
a.augdt,
a.buzei,
v.name1 AS vendor_name,
CASE
WHEN a.zfbdt IS NOT NULL THEN ADD_DAYS(a.zfbdt, COALESCE(a.zbd1t, 0))
ELSE NULL
END AS invoice_due_date
FROM [Schema name].BKPF b
INNER JOIN [Schema name].ACDOCA a
ON a.mandt = b.mandt
AND a.rbukrs = b.bukrs
AND a.belnr = b.belnr
AND a.gjahr = b.gjahr
LEFT JOIN [Schema name].[Vendor master table] v
ON v.[Vendor key field] = a.lifnr
CROSS JOIN params p
WHERE b.bukrs IN ([Company code filter])
AND b.blart IN ([Document type filter])
AND b.cpudt BETWEEN p.start_date AND p.end_date
),
invoice_received AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Received' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(cpudt, 'YYYY-MM-DD') || ' ' || COALESCE(TO_VARCHAR(cputm), '00:00:00')) AS event_time,
CAST(usnam AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
),
invoice_parked AS (
SELECT
CAST([Parked invoice key field] AS NVARCHAR(40)) AS invoice,
'Invoice Parked' AS activity_name,
[Parked event timestamp field] AS event_time,
CAST([Parked user field] AS NVARCHAR(80)) AS user_name,
[Parked company code field] AS company_code,
[Parked vendor name field] AS vendor_name,
[Parked amount field] AS invoice_amount,
[Parked currency field] AS document_currency,
CAST([Parked purchase order field] AS NVARCHAR(40)) AS purchase_order_number,
[Parked due date field] AS invoice_due_date
FROM [Schema name].[Parked document source]
WHERE [Parked event date field] BETWEEN (SELECT start_date FROM params) AND (SELECT end_date FROM params)
AND [Parked company code field] IN ([Company code filter])
),
purchase_order_matched AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Purchase Order Matched' AS activity_name,
COALESCE([Purchase order match timestamp field], TO_TIMESTAMP(TO_VARCHAR(i.cpudt, 'YYYY-MM-DD') || ' ' || COALESCE(TO_VARCHAR(i.cputm), '00:00:00'))) AS event_time,
CAST(COALESCE([Purchase order match user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrBtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Purchase order match source] m
ON m.[Invoice document key field] = i.belnr
AND m.[Invoice company code field] = i.bukrs
AND m.[Invoice fiscal year field] = i.gjahr
WHERE i.ebeln IS NOT NULL
),
goods_receipt_matched AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Goods Receipt Matched' AS activity_name,
[Goods receipt match timestamp field] AS event_time,
CAST(COALESCE([Goods receipt match user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Goods receipt match source] g
ON g.[Invoice document key field] = i.belnr
AND g.[Invoice company code field] = i.bukrs
AND g.[Invoice fiscal year field] = i.gjahr
WHERE i.ebeln IS NOT NULL
),
invoice_blocked AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Blocked For Payment' AS activity_name,
[Payment block timestamp field] AS event_time,
CAST(COALESCE([Payment block user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment block source] b
ON b.[Invoice document key field] = i.belnr
AND b.[Invoice company code field] = i.bukrs
AND b.[Invoice fiscal year field] = i.gjahr
WHERE [Payment block value field] IS NOT NULL
),
discrepancy_resolved AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Discrepancy Resolved' AS activity_name,
[Payment block removal timestamp field] AS event_time,
CAST(COALESCE([Payment block removal user field], i.usnam) AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment block history source] h
ON h.[Invoice document key field] = i.belnr
AND h.[Invoice company code field] = i.bukrs
AND h.[Invoice fiscal year field] = i.gjahr
WHERE [Previous payment block value field] IS NOT NULL
AND [New payment block value field] IS NULL
),
invoice_routed_for_approval AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Routed For Approval' AS activity_name,
[Workflow routed timestamp field] AS event_time,
CAST([Workflow initiator field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow routed event value]'
),
invoice_approved AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Approved' AS activity_name,
[Workflow approval timestamp field] AS event_time,
CAST([Workflow approver field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow approved event value]'
),
invoice_rejected AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Rejected' AS activity_name,
[Workflow rejection timestamp field] AS event_time,
CAST([Workflow rejector field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Workflow event source] w
ON w.[Invoice document key field] = i.belnr
AND w.[Invoice company code field] = i.bukrs
AND w.[Invoice fiscal year field] = i.gjahr
WHERE [Workflow event type field] = '[Workflow rejected event value]'
),
invoice_posted AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Posted' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(budat, 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(usnam AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
WHERE stblg IS NULL
),
payment_proposal_created AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Proposal Created' AS activity_name,
[Payment proposal timestamp field] AS event_time,
CAST([Payment proposal user field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment proposal source] p
ON p.[Invoice document key field] = i.belnr
AND p.[Invoice company code field] = i.bukrs
AND p.[Invoice fiscal year field] = i.gjahr
),
payment_executed AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Executed' AS activity_name,
[Payment execution timestamp field] AS event_time,
CAST([Payment execution user field] AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
INNER JOIN [Schema name].[Payment execution source] p
ON p.[Invoice document key field] = i.belnr
AND p.[Invoice company code field] = i.bukrs
AND p.[Invoice fiscal year field] = i.gjahr
),
invoice_due_date_passed AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Invoice Due Date Passed' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(i.invoice_due_date, 'YYYY-MM-DD') || ' 23:59:59') AS event_time,
CAST(i.usnam AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
WHERE i.invoice_due_date IS NOT NULL
AND TO_TIMESTAMP(TO_VARCHAR(i.invoice_due_date, 'YYYY-MM-DD') || ' 23:59:59') < (SELECT evaluation_ts FROM params)
AND i.augbl IS NULL
),
payment_cleared AS (
SELECT DISTINCT
CAST(i.belnr AS NVARCHAR(40)) AS invoice,
'Payment Cleared' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR(i.augdt, 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(i.usnam AS NVARCHAR(80)) AS user_name,
i.bukrs AS company_code,
i.vendor_name,
i.wrbtr AS invoice_amount,
i.waers AS document_currency,
CAST(i.ebeln AS NVARCHAR(40)) AS purchase_order_number,
i.invoice_due_date
FROM base_invoice i
WHERE i.augbl IS NOT NULL
AND i.augdt IS NOT NULL
),
invoice_cancelled AS (
SELECT DISTINCT
CAST(belnr AS NVARCHAR(40)) AS invoice,
'Invoice Cancelled' AS activity_name,
TO_TIMESTAMP(TO_VARCHAR([Reversal posting date field], 'YYYY-MM-DD') || ' 00:00:00') AS event_time,
CAST(COALESCE([Reversal user field], usnam) AS NVARCHAR(80)) AS user_name,
bukrs AS company_code,
vendor_name,
wrbtr AS invoice_amount,
waers AS document_currency,
CAST(ebeln AS NVARCHAR(40)) AS purchase_order_number,
invoice_due_date
FROM base_invoice
WHERE stblg IS NOT NULL
),
all_events AS (
SELECT * FROM invoice_received
UNION ALL SELECT * FROM invoice_parked
UNION ALL SELECT * FROM purchase_order_matched
UNION ALL SELECT * FROM goods_receipt_matched
UNION ALL SELECT * FROM invoice_blocked
UNION ALL SELECT * FROM discrepancy_resolved
UNION ALL SELECT * FROM invoice_routed_for_approval
UNION ALL SELECT * FROM invoice_approved
UNION ALL SELECT * FROM invoice_rejected
UNION ALL SELECT * FROM invoice_posted
UNION ALL SELECT * FROM payment_proposal_created
UNION ALL SELECT * FROM payment_executed
UNION ALL SELECT * FROM invoice_due_date_passed
UNION ALL SELECT * FROM payment_cleared
UNION ALL SELECT * FROM invoice_cancelled
)
SELECT
invoice AS "Invoice",
activity_name AS "ActivityName",
event_time AS "EventTime",
'SAP S/4HANA' AS "SourceSystem",
(SELECT extraction_ts FROM params) AS "LastDataUpdate",
user_name AS "UserName",
company_code AS "CompanyCode",
vendor_name AS "VendorName",
invoice_amount AS "InvoiceAmount",
purchase_order_number AS "PurchaseOrderNumber",
invoice_due_date AS "InvoiceDueDate"
FROM all_events
WHERE invoice IS NOT NULL
AND event_time IS NOT NULL
ORDER BY "Invoice", "EventTime", "ActivityName"; Các bước
- Đặc tả và thiết kế: Trước khi viết mã, hãy phối hợp với chuyên viên phân tích nghiệp vụ để xác nhận chính xác điều kiện kích hoạt và trường dữ liệu của từng hoạt động trong số 15 hoạt động bắt buộc. Xác định các bảng SAP, loại chứng từ (ví dụ 'KR', 'RE') và mã công ty cần đưa vào phạm vi.
- Tạo chương trình ABAP: Mở ABAP Editor bằng mã giao dịch SE38. Tạo chương trình có thể chạy mới, chẳng hạn Z_PM_AP_INVOICE_EXTRACT. Đặt tiêu đề mô tả rõ mục đích và chọn ứng dụng 'Financial Accounting'.
- Tạo màn hình chọn dữ liệu: Trong chương trình, định nghĩa màn hình chọn dữ liệu bằng các từ khóa PARAMETERS và SELECT-OPTIONS để người dùng nhập khoảng ngày trích xuất (ngày tạo hóa đơn), Company Code đích (BUKRS) và Document Type của hóa đơn cần lấy (BLART). Thêm tham số chỉ định đường dẫn tệp đầu ra trên máy chủ ứng dụng.
- Khai báo dữ liệu: Định nghĩa cấu trúc bảng nội bộ khớp với định dạng nhật ký sự kiện cuối cùng (ví dụ TY_EVENT_LOG), gồm mọi thuộc tính bắt buộc và nên có. Khai báo các bảng nội bộ để lưu dữ liệu lấy từ những bảng SAP như BKPF, BSEG, RBKP, RSEG, CDHDR, CDPOS và REGUH.
- Chọn dữ liệu chính: Bắt đầu logic trích xuất bằng cách chọn tập hóa đơn chính từ RBKP (hóa đơn Logistics) và BKPF (hóa đơn tài chính) theo tiêu chí trên màn hình chọn dữ liệu. Lưu các khóa hóa đơn chính vào bảng nội bộ để dùng cho những lần tra cứu tiếp theo.
- Trích xuất lần lượt từng hoạt động: Với mỗi hóa đơn trong tập chính, thực hiện một loạt truy vấn để tìm dấu thời gian và thông tin chi tiết cho từng hoạt động nghiệp vụ. Ví dụ, truy vấn CDHDR và CDPOS để tìm thay đổi trạng thái chặn thanh toán, truy vấn REGUH và REGUP để lấy dữ liệu đợt thanh toán, truy vấn BKPF để lấy thông tin chi tiết chứng từ đảo. Thêm một bản ghi mới vào bảng nhật ký sự kiện cuối cùng cho mỗi hoạt động tìm được.
- Xử lý sự kiện tính toán: Viết logic ABAP cho các hoạt động không được lưu trực tiếp trong trường bảng. Với sự kiện 'Invoice Due Date Passed', dùng ngày đến hạn của hóa đơn (BSEG-ZFBDT + điều khoản thanh toán) và ngày tất toán (BSEG-AUGDT). Nếu ngày tất toán sau ngày đến hạn, hãy tạo bản ghi sự kiện mới với dấu thời gian là ngày đến hạn.
- Chuyển đổi và bổ sung dữ liệu: Khi thu thập dữ liệu cho từng hoạt động, hãy điền đầy đủ các thuộc tính bắt buộc. Việc này gồm tra cứu tên nhà cung cấp từ LFA1, chuyển ngày và giờ thành một chuỗi dấu thời gian (CONCATENATE...INTO...) và đặt giá trị SourceSystem.
- Tạo tệp đầu ra: Sau khi xử lý và thu thập tất cả hóa đơn cùng hoạt động tương ứng vào bảng nội bộ cuối cùng, dùng các câu lệnh OPEN DATASET, LOOP AT ... TRANSFER và CLOSE DATASET để ghi dữ liệu vào tệp trên máy chủ ứng dụng theo đường dẫn đã chỉ định trên màn hình chọn dữ liệu.
- Tải xuống và chuẩn bị tải lên: Dùng mã giao dịch CG3Y để tải tệp đã tạo từ máy chủ ứng dụng về máy. Đảm bảo tệp được lưu dưới dạng CSV mã hóa UTF-8. Kiểm tra tiêu đề cột khớp với các thuộc tính bắt buộc (Invoice, ActivityName, EventTime, v.v.) trước khi tải lên công cụ process mining.
Cấu hình
- Khoảng ngày: Đặt tùy chọn chọn P_CPUDT cho ngày tạo hóa đơn (BKPF-CPUDT hoặc RBKP-CPUDT). Với lần phân tích đầu tiên, nên dùng dữ liệu trong khoảng 6-12 tháng.
- Company Code (P_BUKRS): Tham số SELECT-OPTIONS bắt buộc để lọc theo các mã công ty cụ thể. Không nên xử lý tất cả mã công ty cùng lúc, trừ khi thực sự cần thiết.
- Invoice Document Type (P_BLART): Tham số SELECT-OPTIONS để lọc các loại chứng từ hóa đơn liên quan. Các loại thường gặp gồm 'KR' (hóa đơn nhà cung cấp), 'KG' (giấy báo có của nhà cung cấp), 'RE' (xác minh hóa đơn Logistics).
- Chế độ chạy: Với lượng dữ liệu lớn, nên chạy chương trình dưới dạng tác vụ nền (SM36/SM37) để tránh hết thời gian chờ trong chế độ hộp thoại. Lên lịch chạy ngoài giờ cao điểm.
- Đường dẫn tệp đầu ra: Dùng PARAMETER để chỉ định đường dẫn và tên tệp trên máy chủ ứng dụng SAP (ví dụ trong thư mục /tmp/). Tệp sẽ được ghi vào đây trước khi tải xuống.
- Điều kiện tiên quyết: Người chạy report cần quyền đọc các bảng FI, CO và MM (BKPF, BSEG, RBKP, RSEG, LFA1), bảng chứng từ thay đổi (CDHDR, CDPOS) và bảng workflow. Ngoài ra, cần đối tượng quyền S_DATASET để ghi tệp lên máy chủ ứng dụng.
Truy vấn mẫu abap
*&---------------------------------------------------------------------*
*& Report Z_PM_AP_INVOICE_EXTRACT
*&---------------------------------------------------------------------*
*& This report extracts Accounts Payable invoice lifecycle events for
*& process mining analysis.
*&---------------------------------------------------------------------*
REPORT z_pm_ap_invoice_extract.
*&---------------------------------------------------------------------*
*& Data Structures
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_event_log,
invoice TYPE belnr_d,
activityname TYPE string,
eventtime TYPE string,
sourcesystem TYPE logsys,
lastdataupdate TYPE string,
username TYPE uname,
companycode TYPE bukrs,
vendorname TYPE name1_gp,
invoiceamount TYPE wrbtr,
purchaseordernumber TYPE ebeln,
invoiceduedate TYPE d,
END OF ty_event_log.
DATA: gt_event_log TYPE TABLE OF ty_event_log.
DATA: gv_system_id TYPE logsys.
DATA: gv_last_update TYPE string.
*&---------------------------------------------------------------------*
*& Selection Screen
*&---------------------------------------------------------------------*
SELECT-OPTIONS: s_bukrs FOR bkpf-bukrs OBLIGATORY,
s_cpudt FOR bkpf-cpudt OBLIGATORY DEFAULT sy-datum,
s_blart FOR bkpf-blart.
PARAMETERS: p_fpath TYPE string OBLIGATORY DEFAULT '/tmp/ap_extract.csv'.
*&---------------------------------------------------------------------*
*& Main Processing Block
*&---------------------------------------------------------------------*
START-OF-SELECTION.
" Get System ID and Update Timestamp
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = gv_system_id
EXCEPTIONS
own_logical_system_not_defined = 1
OTHERS = 2.
CONCATENATE sy-datum sy-uzeit INTO gv_last_update.
" Internal tables for SAP data
DATA: lt_bkpf TYPE TABLE OF bkpf,
lt_rbkp TYPE TABLE OF rbkp.
" Select base documents
SELECT * FROM bkpf INTO TABLE lt_bkpf
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND ( blart = 'KR' OR blart = 'KG' ). " Example FI Invoice Types
SELECT * FROM rbkp INTO TABLE lt_rbkp
WHERE bukrs IN s_bukrs
AND cpudt IN s_cpudt
AND blart IN s_blart
AND blart = 'RE'. " Example MM Invoice Type
" --- Process each invoice document ---
LOOP AT lt_bkpf ASSIGNING FIELD-SYMBOL(<fs_bkpf>).
PERFORM process_invoice USING <fs_bkpf>.
ENDLOOP.
LOOP AT lt_rbkp ASSIGNING FIELD-SYMBOL(<fs_rbkp>).
PERFORM process_mm_invoice USING <fs_rbkp>.
ENDLOOP.
" Write output to file
PERFORM write_output_file.
*&---------------------------------------------------------------------*
*& Form PROCESS_INVOICE (Handles FI Invoices)
*&---------------------------------------------------------------------*
FORM process_invoice USING iv_bkpf TYPE bkpf.
DATA: ls_bseg TYPE bseg,
ls_lfa1 TYPE lfa1,
ld_due_date TYPE d.
DATA: ls_event TYPE ty_event_log.
" Get Vendor and other details from first line item
SELECT SINGLE * FROM bseg INTO ls_bseg
WHERE bukrs = iv_bkpf-bukrs
AND belnr = iv_bkpf-belnr
AND gjahr = iv_bkpf-gjahr
AND koart = 'K'.
IF sy-subrc = 0.
SELECT SINGLE name1 FROM lfa1 INTO ls_lfa1-name1 WHERE lifnr = ls_bseg-lifnr.
CALL FUNCTION 'DETERMINE_DUE_DATE'
EXPORTING
i_zfbdt = ls_bseg-zfbdt
i_zbd1t = ls_bseg-zbd1t
i_zbd2t = ls_bseg-zbd2t
i_zbd3t = ls_bseg-zbd3t
i_zbd1p = ls_bseg-zbd1p
i_zbd2p = ls_bseg-zbd2p
i_zterm = ls_bseg-zterm
IMPORTING
e_faedt = ld_due_date.
ENDIF.
" Helper function to populate common fields
MACRO set_common_fields.
ls_event-invoice = iv_bkpf-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_bkpf-bukrs.
ls_event-vendorname = ls_lfa1-name1.
ls_event-invoiceduedate = ld_due_date.
SELECT SINGLE wrbtr FROM bseg INTO ls_event-invoiceamount WHERE belnr = iv_bkpf-belnr AND gjahr = iv_bkpf-gjahr AND koart = 'K'.
ENDMACRO.
" 1. Invoice Received
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
" 2. Invoice Parked (if document was created as parked)
IF iv_bkpf-bstat = 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Parked'.
CONCATENATE iv_bkpf-cpudt iv_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 10. Invoice Posted (For non-parked, same as received. For parked, this needs CDHDR/CDPOS logic not shown for brevity)
IF iv_bkpf-bstat <> 'V'.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Posted'.
CONCATENATE iv_bkpf-budat iv_bkpf-cputm INTO ls_event-eventtime. " Using posting date
ls_event-username = iv_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
" 5. & 7. Invoice Blocked / Discrepancy Resolved from Change Docs
DATA: lt_cdhdr TYPE TABLE OF cdhdr, lt_cdpos TYPE TABLE OF cdpos.
DATA(ld_objectkey) = |{ iv_bkpf-bukrs }{ iv_bkpf-belnr }{ iv_bkpf-gjahr }|.
SELECT * FROM cdhdr INTO TABLE lt_cdhdr WHERE objectclas = 'BELEG' AND objectid = ld_objectkey.
IF sy-subrc = 0.
SELECT * FROM cdpos INTO TABLE lt_cdpos FOR ALL ENTRIES IN lt_cdhdr
WHERE changenr = lt_cdhdr-changenr AND tabname = 'BSEG' AND fname = 'ZLSPR'.
LOOP AT lt_cdpos ASSIGNING FIELD-SYMBOL(<fs_cdpos>).
READ TABLE lt_cdhdr ASSIGNING FIELD-SYMBOL(<fs_cdhdr>) WITH KEY changenr = <fs_cdpos>-changenr.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
IF <fs_cdpos>-value_new IS NOT INITIAL AND <fs_cdpos>-value_old IS INITIAL.
ls_event-activityname = 'Invoice Blocked For Payment'.
ELSEIF <fs_cdpos>-value_new IS INITIAL AND <fs_cdpos>-value_old IS NOT INITIAL.
ls_event-activityname = 'Discrepancy Resolved'.
ELSE.
CONTINUE.
ENDIF.
CONCATENATE <fs_cdhdr>-udate <fs_cdhdr>-utime INTO ls_event-eventtime.
ls_event-username = <fs_cdhdr>-username.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDLOOP.
ENDIF.
" 6. 8. 9. Workflow Events (Routed, Approved, Rejected) - Simplified Example
" This requires knowledge of specific workflow templates. Placeholder logic:
" SELECT ... FROM SWW_WI2OBJ ... WHERE INSTID = [Invoice Object]
" SELECT ... FROM SWWWIHEAD ... to get status and times
" 11. & 12. & 14. Payment Proposal, Executed, Cleared
IF ls_bseg-augbl IS NOT INITIAL.
DATA: ls_regup TYPE regup.
SELECT SINGLE * FROM regup INTO ls_regup WHERE vblnr = ls_bseg-belnr.
IF sy-subrc = 0.
DATA(ld_rundate) = ls_regup-laufd.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Proposal Created'.
CONCATENATE ld_rundate '000000' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Executed'.
CONCATENATE ls_bseg-augdt '120000' INTO ls_event-eventtime. " Using clearing date as proxy
APPEND ls_event TO gt_event_log.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Payment Cleared'.
CONCATENATE ls_bseg-augdt '120001' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
" 13. Invoice Due Date Passed (Calculated)
IF ls_bseg-augdt IS NOT INITIAL AND ld_due_date IS NOT INITIAL.
IF ls_bseg-augdt > ld_due_date.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Due Date Passed'.
CONCATENATE ld_due_date '235959' INTO ls_event-eventtime.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
" 15. Invoice Cancelled
IF iv_bkpf-stblg IS NOT INITIAL.
DATA: ls_rev_bkpf TYPE bkpf.
SELECT SINGLE * FROM bkpf INTO ls_rev_bkpf WHERE belnr = iv_bkpf-stblg.
IF sy-subrc = 0.
CLEAR ls_event.
set_common_fields.
ls_event-activityname = 'Invoice Cancelled'.
CONCATENATE ls_rev_bkpf-cpudt ls_rev_bkpf-cputm INTO ls_event-eventtime.
ls_event-username = ls_rev_bkpf-usnam.
APPEND ls_event TO gt_event_log.
ENDIF.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form PROCESS_MM_INVOICE (Handles MM/Logistics Invoices)
*&---------------------------------------------------------------------*
FORM process_mm_invoice USING iv_rbkp TYPE rbkp.
" This form would be similar to PROCESS_INVOICE, but starts with RBKP.
" It needs to find the corresponding FI document in BKPF via AWKEY.
" The logic for PO/GR Matched would be included here.
" For demonstration, creating placeholder events for MM-specific activities.
DATA: ls_event TYPE ty_event_log.
ls_event-invoice = iv_rbkp-belnr.
ls_event-sourcesystem = gv_system_id.
ls_event-lastdataupdate = gv_last_update.
ls_event-companycode = iv_rbkp-bukrs.
" 1. Invoice Received (MM)
ls_event-activityname = 'Invoice Received'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 3. Purchase Order Matched (Implicit)
ls_event-activityname = 'Purchase Order Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" 4. Goods Receipt Matched (Implicit)
ls_event-activityname = 'Goods Receipt Matched'.
CONCATENATE iv_rbkp-cpudt iv_rbkp-cputm INTO ls_event-eventtime.
ls_event-username = iv_rbkp-usnam.
APPEND ls_event TO gt_event_log.
" NOTE: The rest of the events (Block, Pay, etc.) would be found by linking
" RBKP to BKPF and then reusing the logic from PROCESS_INVOICE.
" Link: BKPF-AWKEY = CONCATENATE( RBKP-BELNR, RBKP-GJAHR ).
ENDFORM.
*&---------------------------------------------------------------------*
*& Form WRITE_OUTPUT_FILE
*&---------------------------------------------------------------------*
FORM write_output_file.
DATA: lv_string TYPE string.
OPEN DATASET p_fpath FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc <> 0.
MESSAGE 'Error opening file.' TYPE 'E'.
RETURN.
ENDIF.
" Write Header
lv_string = 'Invoice,ActivityName,EventTime,SourceSystem,LastDataUpdate,UserName,CompanyCode,VendorName,InvoiceAmount,PurchaseOrderNumber,InvoiceDueDate'.
TRANSFER lv_string TO p_fpath.
" Write Data
LOOP AT gt_event_log ASSIGNING FIELD-SYMBOL(<fs_event>).
" Create a comma-separated string, handling potential commas in data
CONCATENATE <fs_event>-invoice
<fs_event>-activityname
<fs_event>-eventtime
<fs_event>-sourcesystem
<fs_event>-lastdataupdate
<fs_event>-username
<fs_event>-companycode
<fs_event>-vendorname
<fs_event>-invoiceamount
<fs_event>-purchaseordernumber
<fs_event>-invoiceduedate
INTO lv_string SEPARATED BY ','.
TRANSFER lv_string TO p_fpath.
ENDLOOP.
CLOSE DATASET p_fpath.
WRITE: / 'Extraction complete. File written to:', p_fpath.
ENDFORM. Bạn đã sẵn sàng bắt đầu chưa?
Dùng mẫu này để khởi động sáng kiến process mining và nâng cao hiệu quả vận hành khoản phải trả. Bắt đầu cải tiến quy trình ngay hôm nay để quy trình gọn hơn, hiệu quả hơn.
Tránh phí trả chậm: cải thiện quy trình xử lý hóa đơn phải trả ngay hôm nay
Giảm 60% chi phí xử lý và dễ dàng loại bỏ các khoản thanh toán trùng lặp.
Không cần thẻ tín dụng. Bắt đầu chỉ trong vài phút.