The Problem
In many businesses, the same product is sold in different units of measure depending on the customer, the order type, or the packaging: one customer orders in individual Bottles (BT), another in Cartons (CAR), and yet another in full Pallets (PAL). This is common practice within a single sales organization and has no impact on the sales or logistics process. However, it creates a reporting challenge in Margin Analysis.
The apps of the Market Segments family — such as Profitability — Market Segments — display quantity measures (Valuation Quantity, Act Valuation Qty, Act Reference Qty, Act Qty in Base Unit) in whichever unit of measure was used on the originating billing document. Without a conversion to a unified base unit, it is impossible to aggregate or compare sold volumes across line items, customers, or periods. Customers want to see their contribution margin not only per sales unit — which differs by packaging — but also per base unit, enabling a true like-for-like comparison.
Operating across multiple sales organizations that invoice in different units adds a further dimension to the same challenge, but the core problem is already present within a single sales organization.
You may notice that apps in the Sales Volumes family do not have this problem: they correctly convert quantities to a unified base unit. This is not a bug in either app family — it reflects a fundamental difference in where each reads its data.
| Market Segments Apps | Sales Volumes Apps |
Data source | Universal Journal (ACDOCA) — CO document items | Billing document tables (VBRP) |
UoM at posting time | Billing/sales UoM stored as-is in the CO document | Full SD document chain with material master conversion available |
Result | Shows original sales unit (e.g., 30 CAR) | Can convert to base unit (e.g., 300 BT) |
When a billing document is posted, the SD-to-CO transfer writes the billing quantity into the CO document item and from there into ACDOCA in the billing UoM, without converting to the material's base unit. The Quantity Conversion Extension described in this blog closes this gap by populating additional quantity fields at posting time.
Section 1: Prerequisites — Product Master Data Setup
To demonstrate the Quantity Conversion Extension, three products representing the same physical item — water — are created, each sold in a different packaging unit. All three products are set up in the Manage Product Master Data app in SAP S/4HANA Cloud Public Edition.
Figure 1: Overview of the three products RR01, RR02, RR03 in Manage Product Master Data
All three products are of type Trading Goods (HAWA) and share the same base unit: Bottle (BT). This is a critical design choice — the base unit acts as the common denominator to which all alternative units are converted.
Product RR01 — Water - Bottle
RR01 has only one unit of measure defined: Bottle (BT), with a self-referencing conversion of 1 BT = 1 BT. This is the simplest case — the product is sold in its base unit, so no conversion is needed.
Figure 2: RR01 — Units of Measure, base unit Bottle (BT) only
Product RR02 — Water - Carton
RR02 has two units of measure: Bottle (BT) as the base unit, and Carton (CAR) as an alternative sales unit with the conversion factor 1 CAR = 10 BT. This conversion factor, defined on the General Information tab under Units of Measure, tells the system how many bottles are contained in one carton.
Figure 3: RR02 — Units of Measure showing 1 CAR = 10 BT
On the Distribution Chains tab, the Sales Unit for Sales Organization 1010 / Direct Sales (10) is set to Carton (CAR). This means sales orders for RR02 default to CAR as the invoicing unit.
Figure 4: RR02 — Distribution Chains showing Sales Unit = CAR
Product RR03 — Water - Pallet
RR03 follows the same pattern with a larger packaging unit: Bottle (BT) as the base unit, and Pallet (PAL) with the conversion factor 1 PAL = 180 BT. One pallet contains 180 bottles (equivalent to 18 cartons of 10 bottles each).
Figure 5: RR03 — Units of Measure showing 1 PAL = 180 BT
Accordingly, the Sales Unit for this product is set to Pallet (PAL) in the Distribution Chains.
Figure 6: RR03 — Distribution Chains showing Sales Unit = PAL
Why This Setup Matters
The conversion factors defined in the product master are the foundation of the entire Quantity Conversion Extension. Without them, there is no basis for converting quantities at any point in the process. The table below shows the full picture — base unit, sales unit, and the conversion factor for each product:
Product ID | Description | Base Unit | Sales Unit of Measure | Conversion Factor |
RR01 | Water - Bottle | Bottle (BT) | Bottle (BT) | 1 BT = 1 BT |
RR02 | Water - Carton | Bottle (BT) | Carton (CAR) | 1 CAR = 10 BT |
RR03 | Water - Pallet | Bottle (BT) | Pallet (PAL) | 1 PAL = 180 BT |
Note: Every product sold in a non-base unit must have its alternative UoM conversion defined on the product master before any sales orders or billing documents are created. Missing conversions will cause the extension to fall back to the original sales unit quantity.
Section 3: Creating the BAdI Implementation in the Custom Logic App
The Quantity Conversion Extension is created entirely through the Custom Logic app — no external development tools or transport requests are required. This app is SAP's entry point for BAdI-based extensibility in SAP S/4HANA Cloud Public Edition, fully aligned with the Clean Core principle.
Step 1 — Find the Extension Point
Open the Custom Logic app and choose New Implementation. In the Extension Point search field, enter FIN_CODOC_ITEM_QUANTITY and press Search.
Figure 8: Searching for BAdI FIN_CODOC_ITEM_QUANTITY in the Custom Logic app
The system returns exactly one result:
Description | ID |
Controlling Document Line Item Additional Quantities | FIN_CODOC_ITEM_QUANTITY |
This BAdI is called every time a Controlling document line item is created — for example, when a billing document is transferred to Margin Analysis. The View Documentation link provides the full interface specification directly in the system. Select the entry and proceed to Step 2.
Step 2 — Implementation Attributes
In the Implementation Attributes section, BAdI filters can optionally be defined to restrict when the implementation is executed. In this scenario, no filters are needed — the extension applies to all relevant postings, so the Filters table is left empty.
Step 3 — Implementation ID
Figure 9: Implementation Attributes and Implementation ID
Field | Value |
Implementation Description | Additional Product Quantities |
Implementation ID | YY1_ADDITIONALPRODUCTQUANTITIE |
The prefix YY1_ is the customer namespace for custom implementations in SAP S/4HANA Cloud Public Edition, ensuring clean separation from SAP standard objects. Once the details are entered, click Review to validate, then Create to generate the implementation shell.
Section 4: Implementing the Code in the Custom Logic Editor
After clicking Create, the system opens the Custom Logic code editor. The implementation is developed on the Develop tab. The right-hand panel shows all available BAdI parameters — two importing structures are key:
Structure | Description | Key Fields Used |
CODOCHEADER | CO Document Header | REFERENCEDOCUMENTTYPE (VBRK = Billing, MKPF = Material Doc) |
CODOCITEM | CO Document Line Item | MATERIAL, TOTALQUANTITY, UNITUOM, PLANT, SALESORGANIZATION |
The output variables ADDITIONALQUANTITY1, ADDITIONALQUANTITY1UNIT, ADDITIONALQUANTITY2, and ADDITIONALQUANTITY2UNIT are writable — the code writes the calculated values into them before the CO document item is persisted to ACDOCA.
Figure 10: Custom Logic editor — published code and BAdI parameter panel
The Code
IF codocitem-material IS NOT INITIAL AND
( codocheader-referencedocumenttype = 'MKPF' OR
codocheader-referencedocumenttype = 'VBRK' ).
IF codocitem-unituom IS NOT INITIAL.
"AdditionalQuantity1: Convert Sales UoM to base unit for billing docs.
"For material documents the quantity is already in base unit.
IF codocheader-referencedocumenttype = 'VBRK'.
SELECT SINGLE
GrossWeight,
WeightUnit,
QuantityNumerator,
QuantityDenominator,
BaseUnit
FROM I_ProductUnitsOfMeasure
WHERE Product = @codocitem-material
AND AlternativeUnit = @codocitem-unituom
INTO @DATA(ls_uom).
IF sy-subrc = 0.
additionalquantity1unit = ls_uom-baseunit.
additionalquantity1 = codocitem-totalquantity
* ls_uom-quantitynumerator
/ ls_uom-quantitydenominator.
ELSE.
additionalquantity1unit = codocitem-unituom.
additionalquantity1 = codocitem-totalquantity.
ENDIF.
ELSE.
"MKPF: quantity already in base unit
additionalquantity1unit = codocitem-unituom.
additionalquantity1 = codocitem-totalquantity.
ENDIF.
"AdditionalQuantity2: Gross weight of the posted quantity
"Step 1: Try to read weight directly for the UoM of the posting
IF ls_uom IS INITIAL.
SELECT SINGLE
GrossWeight,
WeightUnit,
QuantityNumerator,
QuantityDenominator,
BaseUnit
FROM I_ProductUnitsOfMeasure
WHERE Product = @codocitem-material
AND AlternativeUnit = @codocitem-unituom
INTO @LS_uom.
ENDIF.
IF sy-subrc = 0 AND ls_uom-GrossWeight IS NOT INITIAL.
"Weight is maintained per UoM — multiply directly
additionalquantity2 = codocitem-totalquantity * ls_uom-GrossWeight.
additionalquantity2unit = ls_uom-WeightUnit.
RETURN.
ENDIF.
"Step 2: Fall back to base-unit weight from I_Product
SELECT SINGLE
GrossWeight,
WeightUnit,
BaseUnit
FROM I_Product
WHERE Product = @codocitem-material
INTO @DATA(ls_product).
IF sy-subrc = 0 AND ls_product-GrossWeight IS NOT INITIAL.
"Use base-unit quantity (additionalquantity1) x weight per base unit
additionalquantity2 = additionalquantity1 * ls_product-GrossWeight.
additionalquantity2unit = ls_product-weightunit.
ELSE.
"No weight data available
additionalquantity2 = 0.
CLEAR additionalquantity2unit.
ENDIF.
ENDIF.
ENDIF.
Code Walkthrough
Entry Condition
The BAdI is called for every CO document item. The code only acts when a material is present on the line item and the posting originates from a billing document (VBRK) or a material document / goods issue (MKPF). All other document types — manual journal entries, allocations — are skipped.
Additional Quantity 1 — Base Unit Quantity
The behavior of Additional Quantity 1 differs depending on the source document type.
For billing documents (VBRK), the CO document item carries the quantity in the sales unit of measure — the unit the customer was invoiced in (e.g., CAR or PAL). The system does not automatically convert this to the base unit when writing to ACDOCA. The extension therefore performs this conversion explicitly by reading the product's UoM conversion factors from the released CDS view I_ProductUnitsOfMeasure. The result is the quantity expressed in the product's base unit — for example, 30 CAR becomes 300 BT. If no conversion record exists, the original sales unit quantity is used as a safe fallback.
For material documents (MKPF) — such as goods issues — SAP already converts the quantity to the base unit automatically during posting. No additional conversion is needed, so the code simply passes the existing quantity and unit through to Additional Quantity 1 unchanged.
Additional Quantity 2 — Product Mass
For all document types (both VBRK and MKPF), Additional Quantity 2 is populated with the gross weight of the posted quantity. This enables weight-based analysis in the Market Segments apps regardless of whether the posting originated from a billing or a goods movement.
The weight is determined in two steps: first by checking whether a gross weight is maintained directly on the alternative unit of measure in I_ProductUnitsOfMeasure; if not, by falling back to the base-unit weight from I_Product and multiplying it by the base-unit quantity already calculated in Additional Quantity 1.
Key Design Decisions
Decision | Rationale |
Only VBRK and MKPF | Avoids unintended side effects on other CO posting types |
I_ProductUnitsOfMeasure (CDS view) | Released SAP API — clean core compliant |
Fallback to original UoM if no conversion found | Prevents data loss for products without alternative UoM definitions |
Two-step weight logic | Supports both detailed per-UoM weight maintenance and simpler base-unit weight setups |
Publishing the Implementation
Once the code is saved, it is in draft status and not yet active. To activate the extension, click Publish in the Custom Logic editor. After publishing, the editor confirms the activation with the publisher name and timestamp. From this point on, every new CO document item created from a billing document or material document will be processed by the BAdI.
Note: Only published implementations are active. If you later edit the code, the changes remain in draft until you publish again. The previously published version continues to run in the meantime.
Section 5: Creating the Sales Order
With the product master data configured and the Quantity Conversion Extension published, we use the Manage Sales Orders app to create Sales Order 14487 — a Standard Order (OR) with three line items, one for each of the three water products.
Figure 11: Sales Order 14487 — Items tab showing three products with different sales units
Item | Product | Requested Quantity | Sales Unit |
10 | RR01 — Water - Bottle | 100 | BT |
20 | RR02 — Water - Carton | 30 | CAR |
30 | RR03 — Water - Pallet | 2 | PAL |
Each item automatically defaults to the sales unit configured on the product master's Distribution Chains. This reflects a realistic scenario where different sales channels invoice the same physical product in different packaging units — precisely where the reporting challenge arises.
With the extension active, once this order is billed, the BAdI will convert all quantities to the base unit Bottle (BT) in Additional Quantity 1:
Item | Sales Quantity | Conversion | Additional Quantity 1 (BT) |
10 — RR01 | 100 BT | 1 BT = 1 BT | 100 |
20 — RR02 | 30 CAR | 1 CAR = 10 BT | 300 |
30 — RR03 | 2 PAL | 1 PAL = 180 BT | 360 |
Total |
|
| 760 BT |
Section 6: Verifying the Result in the Product Profitability Review Booklet (Ledger 0E)
Context — Predictive Accounting and Ledger 0E
If the scope item Predictive Accounting for Incoming Sales Orders is activated, SAP S/4HANA Cloud Public Edition already posts predicted revenues and COGS to Ledger 0E at the time the sales order is saved — before delivery or billing occurs. The Quantity Conversion Extension applies equally to these Predictive Accounting postings, since they also create CO document line items processed by the BAdI.
Setup in the Product Profitability Review Booklet
We open the Product Profitability Review Booklet app and apply the following settings: Ledger 0E, Products RR01/RR02/RR03, and a Page Filter for Sales Document 14487. In the layout, Product Sold and Source Ledger are selected as columns.
We also add a custom calculated measure CM I per Base Unit using the Create Calculation functionality:
Figure 12: Create Calculation — CM I per Base Unit formula
Field | Value |
Description | CM I per Base Unit |
ID | MARGINBASEUNIT |
Formula | [ContrbnMargin1AmtInDspCrcy] / [BlldAddl1QuantityInAddl1Unit] |
Results in Ledger 0E
Figure 13: Product Profitability Review Booklet — Ledger 0E, Sales Document 14487
Measure | Unit | RR01 — Water-Bottle | RR02 — Water-Carton | RR03 — Water-Pallet |
Contribution Margin I | EUR | 21,00 | 46,50 | 55,80 |
Recognized Revenue | EUR | 121,00 | 346,50 | 415,80 |
COGS Variable | EUR | -100,00 | -300,00 | -360,00 |
Billed Quantity |
| 100 BT | 30 CAR | 2 PAL |
Margin per Unit (CM I) |
| 0,21 EUR/BT | 1,55 EUR/CAR | 27,90 EUR/PAL |
Billed Additional Qty 1 | BT | 100 | 300 | 360 |
Shipped Quantity | BT | 100 | 300 | 360 |
CM I per Base Unit | EUR/BT | 0,21 | 0,16 | 0,16 |
Billed Quantity reflects the original sales units (100 BT, 30 CAR, 2 PAL). Billed Additional Quantity 1 shows all products unified in Bottle (BT). Shipped Quantity also shows the base-unit quantities, confirming that SAP automatically handles this for material documents. CM I per Base Unit delivers a fully comparable margin metric across all three products.
Section 7: Delivery, Billing, and the Complete Process Flow
With the sales order in place, we process the outbound delivery and create the billing document. The full document chain can be traced on the Process Flow tab of Sales Order 14487.
Figure 14: Sales Order 14487 — Process Flow showing the complete document chain
Step | Document | Status |
Order Processing | 14487 | Completed |
Delivery Processing | 80007474 | Shipped |
Billing | 90003192 | Completed |
Accounting | 9400000320 | Not Cleared |
The green checkmarks on all steps confirm successful completion. The Accounting document is posted but not yet cleared by an incoming payment — expected status at this point.
Posting to Ledger 0L
With the billing document completed, revenue and COGS are now posted in Ledger 0L — the leading operational ledger. Two CO document items are created:
- From the billing document (VBRK): The Quantity Conversion Extension converts billing quantities from their sales units to the base unit BT and writes the result into Additional Quantity 1. Additional Quantity 2 is populated with the gross weight.
From the delivery / goods issue (MKPF): SAP already converts goods issue quantities to the base unit automatically. The extension passes the quantity through unchanged.
Section 8: Verification in Ledger 0L — Actual Postings
We return to the Product Profitability Review Booklet. The layout now shows both Ledger 0E and Ledger 0L side by side as column dimensions, giving a clear picture of how the predictive postings have been replaced by the actual postings.
Figure 15: Product Profitability Review Booklet — Ledger 0E cleared, Ledger 0L with actual postings
Ledger 0E — Cleared
All values in the Ledger 0E (Commitment/Prediction) columns are now 0 across all three products. Once the billing document was created and posted to Ledger 0L, the system automatically reversed the predicted postings in Ledger 0E. Billed Additional Quantity 1 in Ledger 0E also shows 0, confirming that the reversal covers the additional quantity fields populated by the extension.
Ledger 0L — Actual Values Confirmed
Measure | Unit | RR01 — Water-Bottle | RR02 — Water-Carton | RR03 — Water-Pallet |
Contribution Margin I | EUR | 21,00 | 46,50 | 55,80 |
Recognized Revenue | EUR | 121,00 | 346,50 | 415,80 |
COGS Variable | EUR | -100,00 | -300,00 | -360,00 |
Billed Quantity |
| 100 BT | 30 CAR | 2 PAL |
Margin per Unit (CM I) |
| 0,21 EUR/BT | 1,55 EUR/CAR | 27,90 EUR/PAL |
Billed Additional Qty 1 | BT | 100 | 300 | 360 |
Shipped Quantity | BT | 100 | 300 | 360 |
CM I per Base Unit | EUR/BT | 0,21 | 0,16 | 0,16 |
The results mirror exactly what was observed in Ledger 0E — confirming that the Quantity Conversion Extension works consistently across both ledgers and for both predicted and actual postings.
Conclusion and Summary
This blog has demonstrated how the Quantity Conversion Extension based on BAdI FIN_CODOC_ITEM_QUANTITY addresses a real reporting challenge in SAP S/4HANA Cloud Public Edition: the inability of the Market Segments app family to display quantities in a unified unit of measure when different subsidiaries or sales channels invoice in different sales units.
The solution is built entirely on SAP's supported extensibility framework — no modifications, no custom tables, no transport requests outside the Clean Core model. The steps covered end-to-end are:
- Product Master Data — Define alternative units of measure with conversion factors (e.g., 1 CAR = 10 BT, 1 PAL = 180 BT) and assign the correct sales unit per distribution chain.
- Configuration (SSCUI 102406) — Activate Additional Quantity fields in Profitability Analysis with the appropriate physical dimensions (No dimensions for countable units, Mass for weight).
- Custom Logic App — Create a BAdI implementation for FIN_CODOC_ITEM_QUANTITY (Controlling Document Line Item Additional Quantities) with no filters required.
- ABAP Implementation — For billing documents, convert the sales unit quantity to the base unit using I_ProductUnitsOfMeasure. For material documents, pass the quantity through. Populate Additional Quantity 2 with the gross weight for all document types.
- Publish — Activate the implementation in the Custom Logic app.
The result is verified in the Product Profitability Review Booklet, where Billed Additional Quantity 1 shows all products in the unified base unit, and the calculated measure CM I per Base Unit delivers a comparable margin metric across products — regardless of the invoicing unit. The extension also works seamlessly with Predictive Accounting (Ledger 0E), with predicted postings correctly cleared and replaced by actual Ledger 0L postings once billing is complete.
Outlook — Company Profitability Review Booklet (2702)
We plan to include the Additional Quantity fields also in the Company Profitability Review Booklet with release 2702, so it can also be used for Contribution Margin reporting on product level with both sales unit and base unit measures.
Figure 16: Company Profitability Review Booklet (Ledger 0L)
This blog covers SAP S/4HANA Cloud Public Edition. The BAdI FIN_CODOC_ITEM_QUANTITY and the Additional Quantity fields in Profitability Analysis are available in the current release. The planned extension of the Company Profitability Review Booklet is subject to the standard SAP release process.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.