Draft Handling
RAP / CDS / ODataadvanced

Draft Handling Part 4: Validations, Determinations and Side Effects in Draft

Key takeaway

Place business logic correctly in draft-enabled objects: which determinations run on modify, which on save, how Prepare surfaces validation errors, how messages stay in sync with %state area, and how side effects keep the UI current.

Explanation

📌 KEY POINTS
✅ on modify determinations run on every draft change — the user sees results while typing.

✅ on save determinations run only at activation (e.g. document numbers).

✅ Validations run when listed in Prepare (Save click) and again at activation.

💡 Side effects make Fiori reload derived fields immediately.

━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE

Parts 1–3 covered draft mechanics. Draft changes when your logic runs, because users make many small changes before activating. This part tells you where each piece of logic belongs.

━━━━━━━━━━━━━━━━━━━━
▶ 1. DETERMINATIONS ON MODIFY

  • Run after each triggering change in the draft (a field change is a request).
  • Use for values the user must see immediately: default status, item totals, derived descriptions.
  • Must be cheap and idempotent — they may run dozens of times per session.
  • Together with side effects, the UI shows the new value without a manual refresh.

━━━━━━━━━━━━━━━━━━━━
▶ 2. DETERMINATIONS ON SAVE

  • Run once during activation (save sequence, finalize).
  • Use for values that must be assigned only once or only when the data becomes real: numbers from a number range, final approval data.

⚠️ WATCH OUT: an on-save determination that draws a number during every Prepare would waste numbers — keep number assignment on save (or late numbering).

━━━━━━━━━━━━━━━━━━━━
▶ 3. VALIDATIONS AND PREPARE

  • Validations always run in the save sequence at activation.
  • In draft, users need errors before activation: list validations in "draft determine action Prepare { validation … ; }". Fiori calls Prepare when the user clicks Save.
  • Include child validations: validation Item~validateQuantity.
  • If Prepare reports errors, the draft stays; the user corrects and saves again.

━━━━━━━━━━━━━━━━━━━━
▶ 4. MESSAGES THAT BEHAVE IN DRAFT

Draft messages are persisted with the draft. To make them disappear when fixed:

  • Each validation first appends an empty message with its %state_area for every checked instance (this clears older messages from the same validation).
  • Then it appends errors with the same %state_area, %element for the field and a message class text.
  • For item validations, add %path to the parent so Fiori shows the message on the right object.

━━━━━━━━━━━━━━━━━━━━
▶ 5. SIDE EFFECTS

Declared in the BDEF: "side effects { field Quantity affects field TotalAmount; }" (appropriate level and syntax for your release). They tell Fiori Elements what to reload after a change; without them the value is correct in the backend but stale on screen.

━━━━━━━━━━━━━━━━━━━━
▶ 6. ACTIONS IN DRAFT

Actions can run on draft instances (e.g. "copy from template" while editing) or require active instances (e.g. "approve"). Control this with feature control: disable business actions for drafts (%is_draft = mk-on) if they only make sense on saved data.

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP

  1. Check each determination: on modify (user sees it) or on save (only once)?
  2. Put all user-relevant validations into Prepare.
  3. Add %state_area and %element to every validation message.
  4. Add side effects for every derived field.
  5. Disable approval-type actions for drafts via feature control.

✅ CHECKPOINT: logic runs at the right time, and users see results and errors when they expect them.

Code example

ABAP Code
// ===== BDEF: logic placement for draft =====define behavior for ZR_PurchReq alias PurchaseRequest/* header as before */{  determination setInitialStatus on modify { create; }          // visible immediately  determination setRequestID     on save   { create; }          // once, at activation   validation validateDescription on save { create; field Description; }  validation validateSupplier    on save { create; field Supplier; }   action ( features : instance ) approve result [1] $self;      // disabled for drafts   draft determine action Prepare  {    validation validateDescription;    validation validateSupplier;    validation Item~validateQuantity;                           // child validation too  }   side effects { action approve affects field Status; }} define behavior for ZR_PurchReqItem alias Item/* header as before */{  determination calculateTotal on modify { create; delete; field Quantity, Price; }  validation validateQuantity on save { create; field Quantity; }} " ===== Validation message that behaves in draft =====METHOD validateQuantity.  READ ENTITIES OF zr_purchreq IN LOCAL MODE    ENTITY Item FIELDS ( Quantity RequestUUID ) WITH CORRESPONDING #( keys )    RESULT DATA(items).   LOOP AT items INTO DATA(item).    APPEND VALUE #( %tky = item-%tky  %state_area = 'VALIDATE_QTY' ) TO reported-item. " clear     IF item-Quantity <= 0.      APPEND VALUE #( %tky = item-%tky ) TO failed-item.      APPEND VALUE #( %tky        = item-%tky                      %state_area = 'VALIDATE_QTY'                      %msg        = new_message( id = 'ZPR' number = '020'   " Quantity must be > 0                                                 severity = if_abap_behv_message=>severity-error )                      %element-Quantity = if_abap_behv=>mk-on                      %path-PurchaseRequest-%is_draft   = item-%is_draft      " show under parent                      %path-PurchaseRequest-RequestUUID = item-RequestUUID )        TO reported-item.    ENDIF.  ENDLOOP.ENDMETHOD. " ===== Feature control: no approval on drafts =====" %action-approve = COND #( WHEN r-%is_draft = if_abap_behv=>mk-on"                           THEN if_abap_behv=>fc-o-disabled ... )

Real project scenario

In a draft app, request numbers had large gaps: 4711, 4719, 4726. The number assignment was implemented as a determination on modify, so every draft — including abandoned ones — consumed a number, and some drafts drew numbers several times.
Moving it to an on-save determination (later to late numbering for strict gap-free requirements) fixed the gaps. In the same release, item quantity checks were added to Prepare with %state_area, so users saw errors next to the item when clicking Save, and the messages disappeared as soon as the quantity was corrected.

Common mistakes

  • Number assignment or expensive logic in on-modify determinations.
  • Validations missing from Prepare, so errors appear only at activation.
  • Messages without %state_area that never disappear in draft.
  • Item messages without %path, shown out of context.
  • No side effects, so users see stale totals.
  • Allowing approval actions on unsaved drafts.

Best practices

  • on modify for what users must see; on save for one-time or final values.
  • List all user-relevant validations (including children) in Prepare.
  • Use %state_area, %element and %path in every validation message.
  • Declare side effects for derived fields and action results.
  • Disable business actions on drafts via feature control.

Interview angle

Questions: "How does draft change the timing of determinations and validations?", "What is Prepare?", "Why do draft messages need %state_area?"
Strong answer: on-modify determinations run on each draft change (cheap, idempotent), on-save ones only at activation (numbers, final values); validations run at activation and in Prepare if listed, which Fiori calls on Save; messages are persisted with the draft, so %state_area clears them when fixed, %element highlights fields and %path shows child messages under the parent; side effects refresh the UI.

Practice this lesson

Quick check

1. A quotation draft recalculates tax only on activation, so users see wrong totals while editing. What should change?

2. Users say changing a supplier "did not save", but the draft contains the new value. What is most likely?

3. What is the main purpose of the 'Prepare' phase that is automatically triggered before a draft can be activated?

Interview questions

1. How does draft change where you put determinations and validations?

Answer it in your own words first, then compare.

2. You inherit a draft-enabled RAP BO. What do you review?

Answer it in your own words first, then compare.

Practice more with Interview AI →

Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.

More lessons in this topic

Interview questions on this topic

Related SAP topics