Understanding Determination in SAP RAP

Understanding Determination in SAP RAP

SAP RAP

In this blog, we will implement a simple use case in our Billing Document managed application - automatically filling the item description when a billing item is created. But first let’s understand what a determination actually is.


What is a Determination?

A determination is a piece of business logic that is automatically executed by the RAP framework when specific trigger conditions occur during a transactional lifecycle.

In simple terms:

A determination ensures that certain data is derived, adjusted, or completed automatically when an entity changes.

You don’t call it.
The framework calls it.

You only declare:

  • When it should run

  • What should trigger it

The RAP runtime guarantees execution in the correct transactional phase.


Classical ABAP Analogy

If you have worked in classical GUI transactions like VA01, VF01, or MM01:

When you enter a Material Number, the Description automatically appears.

That logic was usually implemented in:

  • PAI modules

  • User exits

  • BAdIs

  • Screen enhancements

Meaning:

UI flow decided when business logic runs.

In RAP the responsibility shifts:

Classical ABAP RAP
Logic attached to screen event Logic attached to business event
Developer controls timing Framework controls timing
Transaction specific Works for UI, API, background
UI dependent Behavior dependent

So instead of saying:

"When the user presses enter on screen field MATNR, the description shows up"

We say:

"Whenever a new item is created, description must exist"

This is the core mindset change of RAP.


Determination Execution Timing

A determination runs in one of two lifecycle moments.

1) on modify

Runs immediately when fields are changed in transactional buffer. It is used when other logic in the same request depends on the result.

determination calculateAmount on modify { field Quantity, field Price; }

When a determination runs on modify, the calculated values are updated only in the transactional buffer. They are not automatically reflected on the UI immediately.

To refresh the UI with those updated values, Side Effects must be implemented.


2) on save

Runs before data is persisted to database. It is used for completing or adjusting final data.

determination setDefaultValues on save { create; }


Our Use Case

Whenever a Billing Item is created:

The Description field should be automatically filled.

Users should not manually maintain it.


Behavior Definition

Add determination in item entity behavior.

define behavior for ZSAC_I_BILL_ITEM
persistent table zsac_bill_item
lock dependent by _header
authorization dependent by _header
{
  update;
  delete;

  field ( readonly : update, mandatory : create )  ItemNo;

  field ( readonly ) BillId, Description;

  determination determineItemDescription on save { create; }

  association _Header;

  mapping for zsac_bill_item
    {
      BillId             = bill_id;
      ItemNo             = item_no;
      MaterialId         = material_id;
      Description        = description;
      Quantity           = quantity;
      ItemAmount         = item_amount;
      Currency           = currency;
      Uom                = uom;
      CreatedBy          = createdby;
      CreateDat          = createdat;
      LastChangedBy      = lastchangedby;
      LastChangeDat      = lastchangedat;
      LocalLastChangeDat = locallastchangedat;
    }
}

What this means

The framework will call method determineItemDescription:

  • only during save

  • only when item is created

No UI dependency exists.


Behavior Implementation

Now implement the generated method in behavior pool class.

METHOD determineItemDescription.

  READ ENTITIES OF zsac_r_bill_headtp IN LOCAL MODE
    ENTITY zsac_r_bill_itemtp
      FIELDS ( BillId ItemNo MaterialId )
      WITH CORRESPONDING #( keys )
      RESULT DATA(lt_bill_items).

  MODIFY ENTITIES OF zsac_r_bill_headtp IN LOCAL MODE
    ENTITY zsac_r_bill_itemtp
      UPDATE FIELDS ( Description )
      WITH VALUE #( FOR ls_item IN lt_bill_items (
          %tky = ls_item-%tky
          Description = |Item for { ls_item-MaterialId }|
      ) ).

ENDMETHOD.

Important Concept: Transactional Buffer

Determinations work on transactional buffer data, not directly on database tables.

So:

  • READ ENTITIES → reads uncommitted changes

  • MODIFY ENTITIES → updates pending changes

The database is updated only after all lifecycle steps complete.


Testing the Determination

Create a new billing document and add an item.

Provide:

  • Item number

  • Material

  • Quantity

  • Amount

When Save is pressed:

  1. RAP detects new item

  2. Determination triggers

  3. Description is filled

  4. Data is persisted

The user never manually maintained the field.


Why Description is Read Only

field ( readonly ) Description;

The field is controlled by business logic.

Allowing manual input would break consistency between:

  • Material master

  • Transaction data

Hence it is framework controlled.


Typical Use Cases of Determinations

Common scenarios where determinations are appropriate:

  • Default values

  • Derived fields

  • Calculated totals

  • Automatic numbering

  • Data completion before save


Note

When working with determinations, you have to consider the following runtime specifics:

  • In unmanaged scenarios, determinations are only supported for draft instances, not for active instances.

  • The determination result must not change if the determination is executed several times under the same conditions (idempotence).

  • The execution order of determinations is not fixed. If there is more than one determination triggered by the same condition, you cannot know which determination is executed first.

  • Once a determination has been triggered, it must run independently from other determinations.

  • If you create or update an instance and delete it with the same request, it can happen that an EML read operation in a determination on modify fails as instances with the given key cannot be found.

Thanks for reading.