Modernize a synthetic legacy ABAP report with an AI assistant: plain-language explanation, dependency map, a remediation plan mapped to ATC-style findings, refactored code, and a generated unit-test list — with the before/after checklist run both ways. Two traps are planted: a refactor that breaks on an empty table, and a custom Z-table the AI will confidently explain without knowing anything about it.
Ramesh maintains a 2009-vintage ABAP estate at a Chennai auto-parts supplier heading for S/4HANA, and ZR_PLANT_STOCK_RPT is this sprint's specimen: a report everyone runs and nobody has dared touch since its author left. AI assistants are genuinely strong at ABAP archaeology — explaining, mapping, refactoring — and they carry one ERP-specific failure mode worth training against: your Z-tables and Z-logic exist nowhere in any training set, so the model invents plausible semantics for them with full confidence. This lab runs the whole modernization loop and makes you catch that invention in the act.
~90 minutes hands-on · Core tier (maps to module M7 · AI-Accelerated ERP Development, Testing & Migration). No SAP system required for the core path; an optional final step uses a free SAP BTP trial with Joule for Developers.
An AI chat assistant and a text editor, $0. The specimen, zr_plant_stock_rpt.abap — legacy on purpose, defects included:
REPORT zr_plant_stock_rpt.
TABLES: mara, marc.
DATA: BEGIN OF itab OCCURS 0,
matnr LIKE mara-matnr,
werks LIKE marc-werks,
eisbe LIKE marc-eisbe,
descr(40) TYPE c,
END OF itab.
DATA: v_total TYPE i VALUE 0.
SELECT * FROM marc WHERE werks IN ('1100', '1200').
MOVE marc-matnr TO itab-matnr.
MOVE marc-werks TO itab-werks.
MOVE marc-eisbe TO itab-eisbe.
SELECT SINGLE maktx FROM makt INTO itab-descr
WHERE matnr = marc-matnr AND spras = 'E'.
SELECT SINGLE zregion FROM zmm_plant_map INTO itab-descr+30(10)
WHERE zwerks = marc-werks.
IF marc-eisbe > 500.
APPEND itab.
v_total = v_total + 1.
ENDIF.
ENDSELECT.
LOOP AT itab.
WRITE: / itab-matnr, itab-werks, itab-eisbe, itab-descr.
ENDLOOP.
WRITE: / 'Total high-stock items:', v_total.
And the ATC-style checklist, atc-checklist.md — ten findings to grade against, before and after:
[C1] SELECT ... ENDSELECT loop-processing on a database table
[C2] SELECT inside a loop (nested DB access per row)
[C3] SELECT * where a field list is needed
[C4] Internal table with header line (OCCURS / TABLES statement)
[C5] Hardcoded literals for org units (plant values in code)
[C6] Hardcoded language key
[C7] Magic number in business logic (threshold 500)
[C8] Classic WRITE list output (no ALV / no separation of logic and display)
[C9] Offset/length access into a character field (descr+30(10))
[C10] FOR ALL ENTRIES used without an initial-table guard [after-only check]
zr_plant_stock_rpt.abap against C1–C9, quoting the offending line for each hit. Expected: nine findings out of nine applicable — this specimen fails everything it can fail. Save as the before column; the AI has not been consulted yet, deliberately: the checklist is your instrument, and you calibrate it before letting the model near the code.zmm_plant_map. It will typically assert what the table contains, what zregion means, even plausible column lists — none of which it can know, because Z-tables are customer-defined. Mark every claim about the Z-table as UNVERIFIED in your copy of the map.z-table-incident.md with the rule this proves: AI claims about Z-objects are prompts for the data dictionary (SE11) and the developer who owns them, never facts. In a real system you would now pull the actual DDIC definition; here, the lab's ground truth is: zmm_plant_map maps plants to maintenance planning regions for a bolted-on plant-maintenance workflow — nothing the model could have derived.sy-langu, ALV-ready output structure. Then audit the draft for the classic AI-refactor bug: if it used FOR ALL ENTRIES IN lt_marc for the MAKT or Z-table read, what happens when lt_marc is empty? In ABAP, FOR ALL ENTRIES with an empty driver table selects every row in the database table — the WHERE clause silently vanishes. If the draft lacks IF lt_marc IS NOT INITIAL. around that SELECT, you have caught the planted defect; if the model included the guard, remove it mentally and write the failure narrative anyway (what would happen on a plant range returning no rows: full-table MAKT read, wrong report, possible memory dump). Fix the final code either way, and confirm C1–C9 all pass plus C10's guard is present.> 500 or >= 500? the legacy code says >, and your refactor must not silently change it — a one-character behavior contract), missing description test (material with no English MAKT row — the legacy code left descr blank and kept going; preserving that is a decision to record), missing Z-mapping test (plant absent from zmm_plant_map), and multi-plant ordering test (legacy output order was database order; if the business relies on it, the refactor needs an explicit SORT). Save as test-list.md.z-table-incident.md, the final code, and the test list. Optional extension: repeat steps 2 and 5 on a free SAP BTP trial with Joule for Developers in ABAP Cloud — and note where Joule's answers differ from your chat assistant's, especially on the Z-table (an in-system copilot can read your DDIC; that difference is the whole argument for platform-integrated assistants).zmm_plant_map claim UNVERIFIED, and z-table-incident.md contains the confident answer and the reversal side-by-side.sy-langu, the initial-table guard, and unchanged > 500 semantics.Self-grading rubric (pass = 8/10): before-checklist complete with citations (0–2); Z-table hallucination caught, confronted, and written up (0–3); FOR ALL ENTRIES empty-table defect caught or its failure narrative written (0–2); refactor passes all ten checks without behavior drift (0–2); test list hardened beyond the AI draft (0–1).
AI modernizes standard ABAP brilliantly and invents your custom objects fluently — the same conversation contains both. The checklist run both ways, the UNVERIFIED markings on every Z-claim, and the empty-table test are what let you take the speed without inheriting the fiction.