-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsap_export.py
More file actions
92 lines (74 loc) · 3.1 KB
/
sap_export.py
File metadata and controls
92 lines (74 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""VynFi SAP Integration Pack — generate → pull → foreign-key check (Scale+).
Runs a generation job with ``exportFormat: "sap"`` and the S/4HANA CDS
dialect, lists the SAP tables that landed in the archive, parses BKPF +
BSEG into DataFrames, and asserts the document-header / line-item
foreign key holds (``BSEG.BELNR ⊆ BKPF.BELNR``).
Uses the portal's default 8-table set — pass ``tables=[...]`` on
``SapExportConfig`` to request any subset of the 27-table superset
(see ``vynfi.SAP_ALL_TABLES``). A 0.25× credit multiplier applies when
``exportFormat ∈ {sap, saft}``.
Requires pandas: ``pip install vynfi[pandas]``.
"""
from __future__ import annotations
import os
import vynfi
from vynfi import SapExportConfig
client = vynfi.VynFi(api_key=os.environ["VYNFI_API_KEY"], timeout=180.0)
sap = SapExportConfig(
dialect="hana", # S/4HANA CDS (UTF-8 BOM, semicolon, decimal comma)
client="200",
ledger="0L",
source_system="DATASYNTH",
local_currency="EUR",
# tables omitted → portal's default 8-table set
# (bkpf, bseg, acdoca, lfa1, kna1, mara, csks, cepc)
)
print("Submitting SAP export job …")
job = client.jobs.generate_config(
config={
"sector": "retail",
"country": "DE",
"accountingFramework": "ifrs",
"rows": 500,
"companies": 1,
"periods": 2,
"periodLength": "monthly",
"processModels": ["o2c", "p2p"],
"exportFormat": "sap",
"output": {"sap": sap.to_dict()},
},
)
done = client.jobs.wait(job.id, timeout=420)
print(f" job {done.id} → {done.status}")
if done.status != "completed":
raise SystemExit(done.error_detail or "Generation did not complete.")
archive = client.jobs.download_archive(done.id)
print(f"\n{archive}")
tables = archive.sap_tables()
print(f"\nSAP tables in sap_export/: {tables}")
bkpf = archive.sap_table_dataframe("bkpf")
bseg = archive.sap_table_dataframe("bseg")
if bkpf is None or bseg is None:
raise SystemExit("Expected BKPF + BSEG in the archive — check tier and config.")
print(f"\nBKPF: {len(bkpf)} document headers, columns: {list(bkpf.columns[:8])}")
print(f"BSEG: {len(bseg)} line items, columns: {list(bseg.columns[:8])}")
# Foreign-key sanity — the same assertion the DS upstream smoke test makes.
bkpf_ids = set(bkpf["BELNR"])
bseg_ids = set(bseg["BELNR"])
orphans = bseg_ids - bkpf_ids
if orphans:
print(f"\n✗ {len(orphans)} BSEG.BELNR values missing from BKPF — foreign key broken")
else:
print("\n✓ Every BSEG.BELNR resolves to a BKPF.BELNR (FK integrity holds)")
# Show the per-company distribution — useful for multi-company BODS loads.
if "BUKRS" in bkpf.columns:
print("\nBKPF by company code (BUKRS):")
for bukrs, n in bkpf["BUKRS"].value_counts().items():
print(f" {bukrs}: {n}")
archive.close()
print(
"\nTo load these into your SAP S/4HANA test system:"
"\n - UTF-8 BOM + semicolon + decimal comma = BODS/HANA-native format"
"\n - BKPF → document headers, BSEG → line items, ACDOCA → Universal Journal"
"\n - LFA1 / KNA1 / MARA / CSKS / CEPC are master data for referential joins"
)