Go back to the main page

SAP Plan-to-Produce Workflow

S/4HANA IDES — Automated P2Pr Data Generator via JCo RFC
Discrete Manufacturing

Overview

Plan-to-Produce (P2Pr) automated data generator that creates end-to-end production documents via JCo RFC: production order, release, and confirmation with automatic backflush (goods issue + goods receipt). Generates realistic SAP PP transaction data on S/4HANA IDES using the bike finished goods family (MZ-FG-*).

Same SAP system as OTC and P2P. All programs connect to the same S/4HANA IDES instance. No overlap with P2P raw materials (RM12, R-302, etc.) or OTC finished goods (TG11, TG12). Bike family materials (MZ-FG-*, MZ-RM-*) are safe for parallel use.

SAP System

System
S/4HANA IDES (SID: S4H)
Release
758 (HANA DB)
Client
100
Company Code
1710
Plant
1710
Storage Location
171A / 171C
Currency
USD

Production Configuration

Order Type
YBM1 (Standard discrete mfg)
Finished Goods
9 bike models (MZ-FG-*)
Raw Materials
61 components (MZ-RM-*)
BOM Ratio
1:1 (base qty 100,000)
Routing Ops
2 (Assembly + Inspection)
Work Centers
Z_ASM*, Z_INSP*

Local Connectivity

Everything runs from the local Mac — no need to SSH into sapidess4 or sapidesecc8. Client 100 is used for all operations.

SAP RFC via JCo (BAPIs)

Connects directly over the network using JCo 3. No SSH tunnel needed.

ParameterValue
Hostsapidess4.fivetran-internal-sales.com
System Number03 (port 3303)
Client100
UserIDES
Password(see vault)
LanguageEN

Required local files (in ../SAPjco/):

  • sapjco3.jar — Java JCo library
  • libsapjco3.dylib — macOS ARM64 native library
java -Xmx512m -cp .:../SAPjco/sapjco3.jar \
  -Djava.library.path=../SAPjco SAPP2PrWorkflow full 1

HANA Database (direct SQL via hdbcli)

Connect via SSH tunnel for direct SQL. Only the tunnel uses SSH — you never log into the server.

ParameterValue
Tunnellocalhost:30015sapidess4:30015
DatabaseFIV (S/4HANA tenant)
UserSAPHANADB
Password(see vault)
Python libpip3 install hdbcli
# Start SSH tunnel (one-time, runs in background)
ssh -f -N -L 30015:127.0.0.1:30015 root@sapidess4

# Query via Python
python3 -c "
from hdbcli import dbapi
conn = dbapi.connect(address='localhost', port=30015,
    user='SAPHANADB', password='(see vault)', databaseName='FIV')
cur = conn.cursor()
cur.execute(\"SELECT AUFNR, OBJNR FROM AUFK WHERE AUART='YBM1'\")
for row in cur.fetchall(): print(row)
"

Finished Goods (Bike Family)

All finished goods below are FERT materials with BOM + Routing in plant 1710, BESKZ='E' (in-house production), standard price (VPRSV=S).

MaterialDescriptionStd Price (USD)Components
MZ-FG-C900C900 BIKE312.887 ROH
MZ-FG-C950C950 BIKE513.027 ROH
MZ-FG-C990C990 Bike810.007 ROH
MZ-FG-M500M500 BIKE668.167 ROH
MZ-FG-M525M525 BIKE1,119.017 ROH
MZ-FG-M550M550 BIKE2,842.027 ROH
MZ-FG-R100R100 BIKE457.637 ROH
MZ-FG-R200R200 Bike3,100.227 ROH
MZ-FG-R300R300 Bike5,873.887 ROH

Raw Materials (63 Components)

Each bike has 7 ROH components following the naming pattern MZ-RM-{model}-01 through MZ-RM-{model}-07. 9 models × 7 components = 63 raw materials total.

#PartExample (C900)UoMStock Qty
01FrameMZ-RM-C900-01ST10,000
02Handle BarsMZ-RM-C900-02ST10,000
03SeatMZ-RM-C900-03ST10,000
04WheelsMZ-RM-C900-04ST20,000
05ForksMZ-RM-C900-05ST10,000
06BrakesMZ-RM-C900-06ST10,000
07Drive TrainMZ-RM-C900-07ST10,000
Zero initial stock: All bike raw materials have zero stock in IDES. You must run step0-stock (movement type 501, GR without PO) before creating production orders, or Goods Issue (Step 3) will fail with M7/021 insufficient stock.

BOMs & Routing

Bill of Materials Structure

BOM base quantity = 100,000; component quantity = 100,000 → 1:1 ratio per unit produced. BOM type: STLTY='M' (material BOM).

TableDescriptionKey Fields
MASTMaterial-to-BOM linkMATNR, WERKS, STLAN, STLNR
STKOBOM headerSTLNR, STLAL, STLTY='M', BMENG (base qty)
STPOBOM items (components)STLNR, STLKN, IDNRK (component material), MENGE

Routing

Each bike has a 2-operation routing:

OperationWork CenterDescription
0010Z_ASM1 / Z_ASM2 / Z_ASM3Assembly
0020Z_INSP1 / Z_INSP2 / Z_INSP3Inspection
TableDescriptionKey Fields
MAPLMaterial-to-routing assignmentMATNR, WERKS, PLNNR, PLNAL
PLPORouting operationsPLNNR, PLNKN, VORNR, ARBID
CRHDWork center headerOBJID, ARBPL, WERKS

Verification Query

-- Check BOM structure for all bikes
SELECT m.MATNR, k.STLNR, k.STLAL, k.BMENG, p.IDNRK, p.MENGE
FROM MAST m
JOIN STKO k ON m.STLNR = k.STLNR AND k.STLTY = 'M'
JOIN STPO p ON k.STLNR = p.STLNR
WHERE m.MATNR LIKE 'MZ-FG%' AND m.WERKS = '1710'
ORDER BY m.MATNR, p.STLKN;

End-to-End Flow

Step 0 Stock Post
mvt 501
MATDOC
Step 1 Prod Order
AUFK / AFKO
AFPO / RESB
Step 2 Release
JEST
(status)
Step 3 Confirm
AFRU
(yield + time ticket)
Backflush (RGEKZ=1) — Confirmation auto-posts: GI mvt 261 + GR mvt 101
Document Flow: Order (AUFNR) → Reservations (RESB.AUFNR) → Confirmation (AFRU.AUFNR) → auto GI (MATDOC.AUFNR, mvt 261) + auto GR (MATDOC.AUFNR, mvt 101) → Accounting (ACDOCA). Use CO03 to display order details and document flow.
Backflush: All bike raw materials have RGEKZ=1 (Always Backflush) in MARC. During final confirmation, SAP automatically issues components (261) and receives the finished good (101). Manual GI (Step 3) and manual GR (Step 5) are not needed in the automated pipeline.

Step 0 — Raw Material Stock (One-time)

Post Initial Raw Material Stock

Posts initial stock for all 63 raw materials using movement type 501 (GR without PO). Uses GM_CODE = 05 (Other goods receipts). Checks current MARD stock and only posts the delta. This is a one-time setup step.

BAPI

Function ModulePurpose
BAPI_GOODSMVT_CREATEPost goods movement (mvt 501, GM_CODE 05)
RFC_READ_TABLECheck current stock in MARD
BAPI_TRANSACTION_COMMITPersist changes (WAIT='X')

Import Parameters

StructureFieldValue
GOODSMVT_HEADERPSTNG_DATEToday
DOC_DATEToday
GOODSMVT_CODEGM_CODE05 (Other goods receipts)
GOODSMVT_ITEMMATERIALe.g. MZ-RM-C900-01
PLANT1710
STGE_LOC171A
MOVE_TYPE501
ENTRY_QNT10,000 (or 20,000 for Wheels)
ENTRY_UOMST

Tables Populated

TableDescriptionImpact
MATDOCMaterial Document1 document per material
MARDStorage Location StockLABST increased
MBEWMaterial ValuationLBKUM (total stock qty) updated

Step 1 — Production Order

Create Production Order

Creates a production order for a randomly selected bike finished good with order type YBM1 (standard discrete manufacturing). SAP automatically explodes the BOM and creates component reservations in RESB, and copies the routing to order operations (AFVC).

Transaction Codes

TcodePurpose
CO01Create Production Order
CO02Change Production Order
CO03Display Production Order

BAPI

Function ModulePurpose
BAPI_PRODORD_CREATECreate production order with material, qty, dates
BAPI_TRANSACTION_COMMITPersist changes (WAIT='X')

Import Parameters (ORDERDATA structure)

FieldValueNotes
MATERIALe.g. MZ-FG-C900Random bike from pool of 9
PLANT1710
ORDER_TYPEYBM1Standard discrete manufacturing
QUANTITY5–20 (random) or --qty N
BASIC_START_DATEToday
BASIC_END_DATEToday + 5 days
Export: ORDER_NUMBER (12-digit, zero-padded). RETURN is an export structure (not a table) — use getExportParameterList().getStructure("RETURN").

Tables Populated

TableDescriptionKey Fields Written
AUFKOrder Master (header)AUFNR, AUART='YBM1', AUTYP, OBJNR
AFKOOrder Header Data (PP)AUFNR, PLNBEZ (material), GAMNG (qty), AUFPL, GMEIN
AFPOOrder ItemAUFNR, POSNR, MATNR, PSMNG (planned qty), MEINS
AFVCOrder OperationsAUFPL, APLZL, VORNR (0010/0020), ARBID
RESBReservations (component requirements)RSNUM, RSPOS, AUFNR, MATNR, BDMNG (required qty)

Verification Query

-- Production order details
SELECT a.AUFNR, a.PLNBEZ, a.GAMNG, a.GMEIN, a.IGMNG
FROM AFKO a WHERE a.AUFNR = '000001XXXXXX';

-- Component reservations
SELECT RSNUM, RSPOS, MATNR, BDMNG, ENMNG, MEINS
FROM RESB WHERE AUFNR = '000001XXXXXX';

Step 2 — Release Order

Release Production Order

Changes order status from CRTD (Created) to REL (Released), enabling goods movements. A released order can have components issued and finished goods received.

Transaction Codes

TcodePurpose
CO02 (Release button)Release individual order
COHVMass processing (release multiple orders)

BAPI

Function ModulePurpose
BAPI_PRODORD_RELEASERelease one or more production orders
BAPI_TRANSACTION_COMMITPersist changes (WAIT='X')

Parameters

ParameterTypeNotes
ORDERS tableTableORDER_NUMBER field (12-digit)
RETURNExport structureUse getExportParameterList().getStructure("RETURN")
DETAIL_RETURNTableDetailed messages per order

Tables Updated

TableDescriptionImpact
AUFKOrder MasterStatus object (OBJNR) updated
JESTIndividual Object StatusSTAT='I0002' (REL) activated, STAT='I0001' (CRTD) deactivated

Step 3 — Confirmation (auto GI + GR)

Confirm Production Order (Time Ticket)

Reports yield (completed quantity) per operation using time ticket confirmation. Reads AFKO for order qty, AFVC for operations, then posts confirmations with final confirmation (FIN_CONF='X') on the last operation. Because all raw materials have RGEKZ=1 (Always Backflush), the confirmation automatically posts GI (261) and GR (101).

Transaction Codes

TcodePurpose
CO11NEnter Confirmation (Time Ticket)
CO14Display Confirmation
CO13Cancel Confirmation

BAPIs

Function ModulePurpose
RFC_READ_TABLERead AFKO for order quantity (GAMNG, GMEIN, PLNBEZ)
RFC_READ_TABLERead AFVC for operations (VORNR list)
BAPI_PRODORDCONF_CREATE_TTPost time ticket confirmation (per operation)
BAPI_TRANSACTION_COMMITPersist changes (WAIT='X')

TIMETICKETS Table Fields (one row per operation)

FieldValueNotes
ORDERIDProduction order number12-digit
OPERATIONOperation number (from AFVC)e.g., 0010, 0020
POSTG_DATEToday
YIELDOrder quantity (from AFKO.GAMNG)
CONF_ACTI_UNIT1HActivity unit (hours)
CONF_ACTIVITY11.0 (or 0.5 for last op)Explicit activity qty — bypasses cost rate lookup
EXEC_START_DATEToday
EXEC_FIN_DATEToday
FIN_CONFX (last op only)Final confirmation — triggers backflush GI+GR
CLEAR_RESX (last op only)Clear remaining open reservations
Why TT instead of HDR? The header-level BAPI (BAPI_PRODORDCONF_CREATE_HDR) triggers cost rate lookup via CSSL/COST tables, which requires activity rates for the current fiscal year. The time ticket BAPI (BAPI_PRODORDCONF_CREATE_TT) accepts explicit activity quantities per operation, bypassing the cost rate lookup entirely. This avoids RU/085 errors.

Backflush Behavior (RGEKZ=1)

When the final confirmation is posted, SAP automatically performs:

Auto-PostingMvt TypeGM_CODEEffect
Goods Issue (components)26103Raw material stock decreased, 1 MATDOC item per component
Goods Receipt (finished good)10102Finished good stock increased, MBEW updated

Tables Populated

TableDescriptionImpact
AFRUOrder ConfirmationsOne row per operation: AUFNR, VORNR, LMNGA (yield), BUDAT
MATDOCMaterial Document (GI)BWART='261', 1 item per component (auto backflush)
MATDOCMaterial Document (GR)BWART='101', finished good receipt (auto backflush)
MARDStorage Location StockLABST decreased (components) and increased (finished good)
MBEWMaterial ValuationLBKUM, SALK3 updated for finished good
RESBReservationsENMNG (withdrawn qty) updated by backflush
ACDOCAUniversal JournalGI: consumption debit (GBB) + stock credit (BSX). GR: stock debit (BSX) + production variance (PRD)
JESTObject StatusDLV (Delivered) + CNF (Confirmed) activated

Verification Query

-- Confirmations for order
SELECT AUFNR, VORNR, LMNGA, GMNGA, BUDAT, ERSDA
FROM AFRU WHERE AUFNR = '000001XXXXXX';

-- Material documents (GI 261 + GR 101) created by backflush
SELECT MBLNR, BWART, MATNR, MENGE, MEINS, AUFNR
FROM MATDOC WHERE AUFNR = '000001XXXXXX';

SAP Tables Reference

Production Planning Tables

TableDescriptionCategoryPopulated By
AUFKOrder Master (header)Order HeaderStep 1
AFKOOrder Header Data (PP specific)Order MasterStep 1
AFPOOrder ItemOrder ItemsStep 1
AFVCOrder OperationsOperationsStep 1
RESBReservation / Dependent RequirementsReservationsStep 1, updated Step 3 (backflush)
AFRUOrder ConfirmationsConfirmationsStep 3
JESTIndividual Object StatusStatusSteps 1, 2, 3

BOM & Routing Tables

TableDescriptionCategory
MASTMaterial BOM LinkBOM Assignment
STKOBOM HeaderBOM Header
STPOBOM Items (Components)BOM Items
MAPLMaterial-to-Routing AssignmentRouting Assignment
PLPORouting OperationsRouting Ops
CRHDWork Center HeaderWork Centers

Materials Management Tables

TableDescriptionCategoryPopulated By
MATDOCMaterial Document (S/4HANA unified)Mat. DocumentSteps 0, 3 (backflush GI 261 + GR 101)
MARDStorage Location StockStock LevelsSteps 0, 3 (updated by backflush)
MBEWMaterial ValuationValuationSteps 0, 3 (updated by backflush GR)

Financial Accounting Tables

TableDescriptionCategoryPopulated By
ACDOCAUniversal Journal Entry (S/4HANA)Universal JournalStep 3 (backflush GI + GR)
BKPFAccounting Document HeaderFI Doc HeaderStep 3 (backflush GI + GR)

Material Master Tables

TableDescriptionCategory
MARAMaterial General DataGeneral
MARCMaterial Plant Data (MRP, Production)Plant
MARDStorage Location StockStock
MAKTMaterial DescriptionsTexts
MBEWMaterial ValuationValuation

Configuration Tables

TableDescriptionPurpose
T001Company CodesCompany code 1710
T001KValuation AreaPlant-to-company code assignment
T001WPlantsPlant definitions
T003OOrder TypesYBM1, PP01, PP02
T030Account Determination (OBYC)BSX, GBB, PRD transaction keys
MARVMM Posting PeriodCurrent posting period (LFMON/LFGJA)
CKMLHDML Material HeaderMaterial Ledger header per material
CKMLPPML Period RecordsPeriod status (continuous, no gaps)
CKMLCRML Currency RecordsCURTP 10+30 per period

Movement Types

Mvt TypeGM_CODEDescriptionStep
50105GR without PO (initial stock posting)Step 0
26103GI for production order (components)Step 3 (auto backflush)
10102GR for production order (finished good)Step 3 (auto backflush)
26204Return of GI 261 (reversal)
10206GR reversal

Order Types

TypeDescriptionNotes
YBM1Standard discrete manufacturingUsed by automation (bike family)
YBM3Configurable productionNot used
PP01Standard SAP productionSAP default
PP02Standard SAP processProcess manufacturing

S/4HANA vs ECC Table Changes

AreaECC TablesS/4HANA TableNotes
Material DocumentsMKPF + MSEGMATDOCSingle unified table
AccountingBSEG + FAGLFLEXA + COEPACDOCAUniversal Journal
StockMCHB, MSKA, MSSLMARD + MATDOCConsolidated
Material LedgerOptionalAlways activeML infrastructure mandatory in S/4

CDS Views Reference

Production Order CDS Views

CDS ViewDescriptionBase Tables
I_ProductionOrderProduction order headerAUFK, AFKO
I_ProductionOrderItemProduction order itemsAFPO
I_ProductionOrderOperationOrder operationsAFVC
I_ProductionOrderComponentOrder components (reservations)RESB
I_MfgOrderConfirmationOrder confirmationsAFRU

Material Document CDS Views

CDS ViewDescriptionBase Tables
I_MaterialDocumentHeader_2Material document headerMATDOC
I_MaterialDocumentItem_2Material document itemsMATDOC

Material Master CDS Views

CDS ViewDescriptionBase Tables
I_ProductProduct (material) masterMARA, MAKT
I_ProductPlantBasicPlant-level dataMARC
I_ProductValuationValuation dataMBEW
I_BillOfMaterialBOM headerSTKO
I_BillOfMaterialItemBOM itemsSTPO

Fiori Apps

App IDNameStep
F2430Manage Production OrdersOrder
F3703Release Production OrdersRelease
F3422Confirm Production OrderConfirmation
F0843Post GR for POGR
F2432Order Progress OverviewAnalytics

Scripts & Usage

Quick Start (p2prgen.sh)

Generate N production cycles, stopping at any stage:

# First time: post raw material stock
./p2prwf.sh step0-stock --verbose

# Then generate production cycles
./p2prgen.sh 1                    # 1 full cycle (Order→Release→Confirm)
./p2prgen.sh 10 order             # 10 production orders only
./p2prgen.sh 100 release          # 100x Order→Release
./p2prgen.sh 100 confirm          # 100x full pipeline (auto GI+GR)
./p2prgen.sh 10 confirm --qty 10 --verbose

Individual Steps (p2prwf.sh)

./p2prwf.sh step0-stock --verbose               # Post raw material stock
./p2prwf.sh step1-order 5 --verbose              # Create 5 production orders
./p2prwf.sh step2-release <orderNumber>          # Release order
./p2prwf.sh step4-confirm <orderNumber>          # Confirm (auto GI+GR via backflush)
./p2prwf.sh status <orderNumber>                 # Show order details

Stages

StagePipelineSAP Tables Created
orderCreate orderAUFK, AFKO, AFPO, AFVC, RESB
releaseOrder → Release+ JEST (status)
confirmOrder → Release → Confirm (auto GI+GR)+ AFRU, MATDOC (261+101), ACDOCA

Options

FlagDescription
--verbosePrint BAPI details and all return messages
--dry-runValidate only (no BAPI_TRANSACTION_COMMIT)
--stop-at STAGEStop after stage: order, release, confirm (default: confirm)
--pause NSeconds between steps (default: 3)
--qty NFixed production quantity per order (default: random 5-20)

Project Structure

.
┌── SAPP2PrWorkflow.java              # Main automation program
┌── p2prgen.sh                        # Bulk data generator script
┌── p2prwf.sh                         # Workflow wrapper script
┌── compile.sh                        # Compilation helper
┌── docs/
│   └── SAP_PP_Workflow_Documentation.html  # This document
└── skill/
    └── plan-to-produce.md              # Claude Code skill file

Troubleshooting

Common Errors

ErrorCauseFix
C+/065 ML header missing Material Ledger header (CKMLHD) not found Insert CKMLHD for MANDT='100' with KALN1 from client 100 MBEW
C+/073 ML period missing Material Ledger periods have gaps Insert continuous CKMLPP+CKMLCR (CURTP 10+30) for all months, no gaps
M7/021 Insufficient stock Component raw materials have no stock Run step0-stock first to post 10,000 units per material
M3/351 Material not maintained Material does not exist in plant 1710 Verify material exists in MARC for plant 1710. Remove from material list if not present.
RU/085 Error in determining actual costs CSSL/COST activity rate tables missing for current fiscal year Use BAPI_PRODORDCONF_CREATE_TT with explicit CONF_ACTIVITY1 to bypass cost rate lookup
M7/509 No movements for reservation Backflush materials (RGEKZ=1) have XWAOK='X' — reservation-based GI not possible Do NOT post manual GI. Backflush handles GI automatically during confirmation.
M7/022 Order quantity exceeded Manual GR attempted after backflush already posted GR Do NOT post manual GR. Backflush handles GR automatically during confirmation.
No reservations found BOM not exploded or order doesn't exist Verify order in AFKO. Check BOM exists in MAST for plant 1710.
Order stuck in CRTD Release (Step 2) not performed or failed Run step2-release with --verbose to see DETAIL_RETURN
Confirmation rejected Order not released, or already finally confirmed Check status with status command. FIN_CONF=X means final.

Material Ledger Prerequisites

SAP S/4HANA requires continuous CKMLPP period records with no gaps for any goods movement. The same Material Ledger issues documented in the P2P workflow apply here.

TableRequirements
CKMLHDOne row per material. KALN1 from MBEW. MANDT='100'.
CKMLPPOne row per month. STATUS='10' (closed) or '01' (open). No gaps from material creation to current period.
CKMLCRTwo rows per period: CURTP 10 (company code currency) and CURTP 30 (group currency).

ML Verification Query

-- Check ML headers for bike materials
SELECT MATNR, BWKEY, KALN1 FROM MBEW
WHERE MATNR LIKE 'MZ-RM%' AND BWKEY = '1710';

-- Check ML periods (should be continuous)
SELECT KALNR, BDATJ, PESSION, STATUS FROM CKMLPP
WHERE KALNR IN (SELECT KALN1 FROM MBEW WHERE MATNR LIKE 'MZ-RM%' AND BWKEY = '1710')
ORDER BY KALNR, BDATJ, PESSION;

BAPI Parameter Gotchas

BAPIGotchaCorrect Approach
BAPI_PRODORD_CREATE RETURN is export structure, not table. No table parameters at all. getExportParameterList().getStructure("RETURN")
BAPI_PRODORD_CREATE Date fields are BASIC_START_DATE / BASIC_END_DATE Not BASIC_START / BASIC_END
BAPI_PRODORD_RELEASE RETURN is export structure. DETAIL_RETURN is table. Check both for errors
BAPI_PRODORDCONF_CREATE_TT Confirmation table is TIMETICKETS, one row per operation getTableParameterList().getTable("TIMETICKETS")
BAPI_PRODORDCONF_CREATE_TT Must set CONF_ACTIVITY1 + CONF_ACTI_UNIT1 to bypass cost rate lookup (RU/085) Set FIN_CONF='X' and CLEAR_RES='X' only on the last operation
BAPI_GOODSMVT_CREATE GOODSMVT_CODE is a structure, not a string getStructure("GOODSMVT_CODE").setValue("GM_CODE","03")

Test Results

Step 0 — Initial Stock Posting

TestResultDetails
Post stock for 61 raw materialsPASSMatDocs 4900007748–4900007808, 10,000–20,000 EA per material

Single Full Cycle

StepResultDetails
OrderPASSOrder 1002162 (MZ-FG-C950 × 17)
ReleasePASSStatus CRTD → REL
Confirm (auto GI+GR)PASS2 ops confirmed. MatDoc 4900007817 (GR 101) + 4900007818 (GI 261)

Bulk Test — 3 Cycles

MetricValue
Orders created1002163, 1002164, 1002165
Total completed3 / 3
Failures0
All tests performed on SAP S/4HANA IDES, client 100, plant 1710. Confirmation uses BAPI_PRODORDCONF_CREATE_TT (time ticket) with explicit activity quantities.