Posts

Showing posts from August, 2026

Subcontracting vs external processing in S/4HANA: tell them apart by their postings

Both of these mean “someone outside does part of the work.” They are configured differently, they post differently, and picking the wrong one gives you a cost structure you cannot analyse later. The fastest way to keep them straight is not the definition — it is the accounting entry each one produces. What follows are the actual postings from two products made side by side in the same S/4HANA client: kimchi dumplings made by a subcontractor , and shrimp dumplings made in-house with one outsourced operation . Subcontracting: the vendor makes the product We buy the semi-finished product as work . We supply the raw materials, the subcontractor shapes them, and a single goods receipt settles the entire arrangement. That one document fires several OBYC account-determination keys at once: Posting at the subcontract goods receipt Amount OBYC key Dr 5080 raw material consumed — supplied to subcontractor 4,200 GBB · VBO Cr 1050...

GR/IR explained with real documents: why buying something posts nothing to your P&L

Buying 6,700 KRW of pork and wrappers produced four documents, two accounting entries, and zero effect on the profit and loss statement. That surprises people the first time they trace it, and the reason it works that way is the single most useful thing to understand about procurement in SAP. Below is the actual relay, with the real document numbers from a dumpling factory I built from an empty S/4HANA client. Four documents, but only two of them are accounting # Document What it claims Accounting entry 1 Requisition · ME51N EBAN 0199000553 “we want this” — internal only none 2 Purchase order · ME21N EKKO 4500006934 a promise to the vendor none 3 Goods receipt · MIGO 101 MSEG 5000006252 “it physically arrived” Dr 1050 raw material Cr 9010 GR/IR 4 Invoice receipt · MIRO RBKP 5100004739 “the vendor billed us” Dr 9010 GR/IR + input tax Cr 2...

A 36% margin became 6% at month-end, and every posting was correct

On the day we shipped, the billing document said the margin was 36% . Three weeks later, after the close, the same sale carried a margin of 6% . Nobody made a mistake. No posting was reversed. Every document in between was correct. This is the part of SAP that spreadsheets never prepare you for, so it is worth walking through with real numbers. Everything below comes from a small dumpling factory I built from an empty S/4HANA client and drove through one complete business month. 1. The sale looked great A sales order for 20,000 KRW of dumplings, delivered and billed: Step Transaction Effect Sales order VA01 Revenue 20,000 · standard cost of goods 12,800 → expected margin 7,200 (36%) Goods issue VL01N → PGI Cost of goods sold hits the P&L for the first time — at standard Billing VF01 Revenue 20,000, receivable 22,000 (incl. tax) If you stop reading the system here — and a lot of people do, because t...

Two books: an SAP S/4HANA business novel + the complete build record (The Dumpling Factory)

LAUNCH WEEK Use code LAUNCH20 at checkout for 20% off either book or the bundle — through 29 August 2026 . The buttons below already have it applied. Everything on this blog comes from one project: a small Korean dumpling company, built from a completely empty SAP S/4HANA client and driven through a full business month — plan, standard cost, purchase, produce, sell, close. I have now turned that project into two books . Same company, same real numbers, two very different altitudes. BOOK 1 · THE STORY · $25 How Sarah Joined a K-Dumpling Company and Became an SAP Genius A business novel about SAP S/4HANA. Sarah is a junior accountant at a dumpling factory; when 6,700 won of ingredients vanish from the balance sheet overnight, a consultant named J starts teaching her how a company actually works — one posting at a time. By the last chapter she has watched a 36% margin quietly become 6%, with every posting correct and nobody doing anything wron...

Production Order Variance Calculation KKS1 — Fixing KV031 and KV011, and What Lands in COSB

In the last post on cost center variance calculation (KSS1) I noted that the similarly-named KKS1 is a different animal. This is that post: production order variance calculation. I hit two errors on the way in, so we start with their causes and fixes, then verify — by comparing the database before and after — exactly what gets stored where. Environment: controlling area JNC2, plant JNC2, period 2026/008, KRW, three production orders. ※ Screens, menus, and settings may differ depending on your SAP release and system configuration. Two errors before it would even run KV031 ("no target cost version") — version 0 itself existed. What was empty was the variance variant for orders (AWVAO) in OKV6: only the cost-center one (AWVAS) was maintained, which is why KSS1 worked fine while KKS1 refused. Same OKV6 screen, different column. KV011 is an order status problem. Order 1004916 got its goods receipt and final delivery on August 2 — run KKS1 for period 007 and, as of that pe...

Cost Center Month-End in Four Steps — What Does KSS1 Variance Calculation Actually Leave Behind?

This post covers the last stretch of cost center month-end: variance calculation. The four steps are KSS2 (actual cost splitting) → KSS3 (target cost basis display) → KSII (actual price calculation) → KSS1 (variance calculation) — and for each step I compared the database before and after execution to see exactly which tables it touches. Environment: controlling area JNC2, cost center JNC29010, period 2026/007, KRW, S/4HANA 2021. ※ Screens, menus, and settings may differ depending on your SAP release and system configuration. One of the four steps is different in kind KSS3 has no Test Run checkbox and saves nothing. It computes target costs on the fly from the splitting result and actual activity quantities every time you view it. The other three steps each update different tables: T-code Step Test Run Updates KSS2 Actual cost splitting yes COSS KSS3 Target cost display n/a nothing (computed on view) KSII Actual price calculation yes COKL, COSL + CO documents (the on...

Creating a Custom Movement Type in SAP — From OMJJ Through OBYC Account Determination to the FB03 Posting

This post walks through creating custom movement types, actually posting a goods issue with them, and verifying that the intended G/L account shows up in the accounting document. The order: copy a standard movement type in OMJJ to create ZZ1 (other goods issue) and ZZ2 (its reversal), wire up the account in OBYC , post with MIGO , and read the journal entry in FB03 . Environment: client 100, company code CC10. ※ Screens, menus, and settings may differ depending on your SAP release and system configuration. OMJJ — always copy, never create from scratch Movement types are created by copying an existing one; I used 202 (reversal of issue to cost center) as the source. The 11 folders in the Dialog Structure are the full bundle of settings that make up one movement type — of these, only two touch accounting directly: Account Grouping (the account modification key) and Update control (quantity/value updates). In the detail screen of ZZ2, the Internal Control block is greyed out be...

KE27 Ran Without Errors — So Why Are the COGS Detail Value Fields Still Zero?

This time I ran KE27 periodic valuation and hit a puzzling result: the COGS total was filled, but every COGS detail value field stayed zero. The run finished without a single error, which made the cause harder to find. ※ Screens, menus, and settings may differ depending on your SAP release and system configuration. Environment and symptom Operating concern JNC2 (line item table CE1JNC2), period 2026/007, record type F. After running KE27, document 2 was created with Cost of Goods Sold (VV020) = 6,000 — but COGS-Raw Materials, COGS-Labor, COGS-Depreciation, and COGS-Subcontracting were all empty. The original billing line item (document 1) already carried the detail split (6,800 / 3,000 / 3,000), and the execution log showed zero errors . So at first I assumed a valuation setting was missing. Checking the valuation customizing — all fine I walked the CO-PA valuation chain in order: KE4U has valuation strategy JNC assigned to PV 01·02 with record type F; strategy JNC is defin...

Building a CO-PA Profitability Report, Part 2 — A Screen-by-Screen Walkthrough of KE31, KE34 and KE30

Part 1 covered how CO-PA line item tables are separated per operating concern and the build sequence from KEBC to KE30. This time we follow the same path again, but screen by screen — the report-name restriction, element type choices, and formula entry, exactly where you meet them in front of the system. ※ Screens, menus, and settings may differ depending on your SAP release and system configuration. What trips you up first in KE31 Basic Report Report names cannot contain special characters like underscores. Trying to save ZJNC_PA01 throws an error — stick to letters and digits, e.g. ZJNCPA01 . Right after creating the report a popup asks for the currency; I chose Operating concern currency . Move characteristics generously On the Characteristics tab, move the characteristics you need to the right. A Basic Report is less a final deliverable than a way to see how characteristics and value fields behave, so moving everything at once with the "select all" button is fine....

Building a CO-PA Profitability Report, Part 1 — From Operating Concern to KE30 Execution

This series walks through designing and running a SAP CO-PA (Profitability Analysis) report end to end. Part 1 covers how the operating concern relates to the line item table, the build sequence through KEBC → KE31 → KE34 → KE30, and a Report Painter form that includes a calculated row. ※ Screens, menus, and settings may differ depending on your SAP release and system configuration. The goal Against operating concern JNC2 , build a report showing sales quantity, revenue, COGS, and gross margin — where gross margin is a calculated row (revenue minus COGS). Line item tables are separated per operating concern CO-PA actual line items are stored in tables named CE1<ERKRS> . Follow the chain company code → controlling area → operating concern to find yours; a custom program can build the table name dynamically from that assignment. Also important: PALEDGER 01 and 02 can both be stored , so without a ledger filter every query doubles up. Start in KEBC, finish with KE30 Set ...

ZCO0041 — An ABAP Report That Unfolds CO Distribution Cycles (KSV1/KSV3) into One Grid

ZCO0041 is a custom ABAP report that unfolds the definition of CO actual distribution cycles (KSV1/KSV2/KSV3) into a single ALV grid. In KSV3 you have to open a cycle and walk through five tabs per segment (Segment Header, Senders/Receivers, Sender Values, Receiver Tracing Factor, Receiver Weighting Factors); this report flattens all of that into rows you can scan at once — one row = segment × sender cost center × sender cost element × receiver . Selection screen The cycle F4 help is filtered by the controlling area entered on the screen (read at F4 time with DYNP_VALUES_READ , since PAI hasn't run yet). The "only cycles with execution history" checkbox is normally hidden — typing =A in the command field toggles it. Inputs starting with / are intercepted by the kernel as system commands, which is why = is used. Two output modes — summary and expansion A single checkbox ("expand sender/receiver groups and ranges") switches between two modes. Summary c...

Modern ABAP Syntax Notes — Patterns and Pitfalls from Real Development

ABAP syntax actually used while developing our custom Z reports, organized by topic. Examples come from working sources, together with the pitfalls we actually hit. Structure: syntax item → explanation → example code. Last updated: 2026-08-13 1. Data Declarations and Types ▷ Inline declarations DATA(...) / @DATA(...) — Declare and assign in one statement. SELECT result tables land directly in @DATA(lt_...) — the structure is derived from the SELECT list SELECT matnr, maktx FROM makt INTO TABLE @DATA(lt_makt) WHERE spras = @sy-langu. DATA(lv_qty) = ls_stpo-menge * iv_losgr / lv_bmeng. LOOP AT lt_mat INTO DATA(ls_mat). " loop variable inline too ENDLOOP. ▷ FIELD-SYMBOLS / ASSIGNING — Modify internal table rows in place without copying. ASSIGN COMPONENT lets you pick the column name at runtime (used for dynamic logic such as auto-hiding empty columns) LOOP AT gt_list ASSIGNING FIELD-SYMBOL(<ls_list>) WHERE typps = 'M'. <ls_list...

SAP Function Modules & Classes I Actually Use — By Purpose

Function modules (FMs) and classes actually used in our custom developments, organized by purpose. New entries are added whenever a new program is built. Each table: Object / Kind / Purpose / Programs using it. The notes record pitfalls we actually hit. Last updated: 2026-08-13 ALV / Screen Display Object Kind Purpose Used in REUSE_ALV_GRID_DISPLAY FM Classic ALV grid — the standard pattern of our reports ※ The essentials: box_fieldname (selection column), it_sort (sort/subtotals), cfieldname (currency) / qfieldname (unit) references — without the currency reference, KRW amounts display divided by 100 almost every Z report REUSE_ALV_COMMENTARY_WRITE FM TOP-OF-PAGE selection summary ※ SLIS_LISTHEADER-INFO is CHAR(60) — shorten long criteria almost every Z report CL_GUI_ALV_GRID Class OO ALV grid (needs a Custom Control screen) ※ When several grids share one event handler, tell them apart with the event's sender parameter ZJNC launchpad family ...