I have created one managed RAP application to create PurchaseRequisition and store it in a custom table along with messages.
Now I want to extend this application to create PurchaseOrder also and store it along with Vendor details in that same Z table. But I am facing some issue. is it possible to create PO using managed application with Unamanaged Save.
I am also attaching my code for the PR creation scenario.
Behavior Def
managed implementation in class zbp_i_pr_request unique;
strict ( 2 );
define behavior for ZI_PR_REQUEST alias PRReq
//persistent table zpr_request
lock master
authorization master ( instance )
//with additional save
//etag master <field_name>
with unmanaged save
{
create ( authorization : global );
update;
delete;
field ( readonly, numbering : managed ) ReqUuid;
field ( readonly ) Purchaserequisition, Message, Messagetype;
determination createPRAuto on save { create; }
mapping for zpr_request
{
ReqUuid = req_uuid;
Purreqdescription = purreqdescription;
Purchaserequsitiontype = purchaserequsitiontype;
Purchaserequisitionitem = purchaserequisitionitem;
Purchaserequsitionitemtext = purchaserequsitionitemtext;
Plant = plant;
Material = material;
Deliverydate = deliverydate;
Requestedquantity = requestedquantity;
Baseunitisocode = baseunitisocode;
Purchasinggroup = purchasinggroup;
Purchaserequisition = purchaserequisition;
Message = message;
Messagetype = messagetype;
}
}Global Class
CLASS zbp_i_pr_request DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zi_pr_request.
public section.
TYPES: BEGIN OF ty_pr_details,
pid TYPE abp_behv_pid,
cid TYPE abp_behv_cid,
pur_req TYPE zpr_request-purchaserequisition,
req_uuid TYPE zpr_request-req_uuid,
END OF ty_pr_details.
CLASS-DATA purchase_requisition_details TYPE TABLE OF ty_pr_details.
protected section.
private section.
ENDCLASS.
CLASS zbp_i_pr_request IMPLEMENTATION.
ENDCLASS.CreatePr method
METHOD createPRAuto.
READ ENTITIES OF zi_pr_request IN LOCAL MODE
ENTITY PRReq
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(lt_resquest).
LOOP AT lt_resquest ASSIGNING FIELD-SYMBOL(<fs_req>).
IF <fs_req>-Purchaserequisition IS NOT INITIAL.
CONTINUE.
ENDIF.
DATA(lv_cid_hdr) = |PRHDR_{ sy-tabix }|.
DATA(lv_cid_item) = |PRITM_{ sy-tabix }|.
MODIFY ENTITIES OF i_purchaserequisitiontp
ENTITY PurchaseRequisition
CREATE
FIELDS ( purchaserequisitiontype PurReqnDescription )
WITH VALUE #(
( %cid = lv_cid_hdr
PurchaseRequisitionType = <fs_req>-Purchaserequsitiontype
PurReqnDescription = <fs_req>-Purreqdescription ) )
CREATE BY \_purchaserequisitionitem
FIELDS ( purchaserequisitionitem plant material
purchasinggroup requestedquantity baseunit
deliverydate PurchaseRequisitionItemText )
WITH VALUE #(
( %cid_ref = lv_cid_hdr
%target = VALUE #(
( %cid = lv_cid_item
PurchaseRequisitionItem = <fs_req>-PurchaseRequisitionItem
Plant = <fs_req>-Plant
Material = <fs_req>-Material
PurchasingGroup = <fs_req>-PurchasingGroup
RequestedQuantity = <fs_req>-RequestedQuantity
BaseUnit = <fs_req>-BaseUnitISOCode
DeliveryDate = <fs_req>-DeliveryDate
PurchaseRequisitionItemText = <fs_req>-Purchaserequsitionitemtext ) ) ) )
MAPPED DATA(lt_mapped)
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
IF lt_failed IS INITIAL.
READ TABLE lt_mapped-purchaserequisition
INDEX 1
INTO DATA(ls_mapped_pr).
IF sy-subrc = 0.
APPEND VALUE #(
pid = ls_mapped_pr-%pid
cid = ls_mapped_pr-%cid
req_uuid = <fs_req>-ReqUuid
) TO zbp_i_pr_request=>purchase_requisition_details.
ENDIF.
<fs_req>-Messagetype = 'S'.
<fs_req>-Message = 'PR creation initiated successfully'.
ELSE.
<fs_req>-Messagetype = 'E'.
<fs_req>-Message = 'Error occured while creating PR'.
ENDIF.
MODIFY ENTITIES OF zi_pr_request IN LOCAL MODE
ENTITY PRReq
UPDATE FIELDS ( Message Messagetype )
WITH VALUE #( ( %tky = <fs_req>-%tky
Message = <fs_req>-Message
MessageType = <fs_req>-Messagetype ) ).
ENDLOOP.
ENDMETHOD.Save_modfied method
DATA: lt_pr_request_as TYPE STANDARD TABLE OF zpr_request.
IF create-prreq IS NOT INITIAL.
lt_pr_request_as = CORRESPONDING #( create-prreq MAPPING FROM ENTITY ).
INSERT zpr_request FROM TABLE @LT_pr_request_as.
LOOP AT zbp_i_pr_request=>purchase_requisition_details INTO DATA(purchase_reqn_via_eml) WHERE pid IS NOT INITIAL .
CONVERT KEY OF i_purchaserequisitiontp FROM purchase_reqn_via_eml-pid TO DATA(ls_pr_key1).
DATA(lv_pr) = condense( |{ ls_pr_key1-PurchaseRequisition ALPHA = OUT }| ).
DATA(lv_message) = |PR Number { lv_pr } created successfully|.
UPDATE zpr_request SET purchaserequisition = @LV_pr,
message = @LV_message
WHERE req_uuid = @Purchase_reqn_via_eml-req_uuid.
ENDLOOP.
ENDIF.Now how can I adjust the PO creation logic? is it possible so?
ABAP RESTful Application Programming Model ABAP Development SAP S/4HANA Cloud ABAP Environment ABAP Cloud SAP S/4HANA Cloud Public Edition
Request clarification before answering.
Hi,
Yes, it is possible. Your PR pattern (EML call in a determination on save, keep the %pid, CONVERT KEY in save_modified) works the same way for purchase orders with the released BO I_PurchaseOrderTP_2. I checked the BDEFs on an S/4HANA 2025 system (read-only). Please compare them on your release.
What matters in the BDEF
strict ( 2 ), late numbering on the root and on every child entity, no draft. So, like the PR, inside your determination you only get a %pid. The PO number only comes out via CONVERT KEY in your save phase.use create is commented out on the item). It can only be created through the association: CREATE BY \_PurchaseOrderItem.Sketch for the determination (built from the BDEF, not executed):
MODIFY ENTITIES OF i_purchaseordertp_2
ENTITY PurchaseOrder
CREATE FIELDS ( PurchaseOrderType CompanyCode PurchasingOrganization
PurchasingGroup Supplier )
WITH VALUE #( ( %cid = lv_cid_po_hdr
PurchaseOrderType = 'NB'
CompanyCode = lv_bukrs
PurchasingOrganization = lv_ekorg
PurchasingGroup = <fs_req>-Purchasinggroup
Supplier = <fs_req>-Supplier ) )
CREATE BY \_PurchaseOrderItem
FIELDS ( Material Plant OrderQuantity PurchaseOrderQuantityUnit
PurchaseRequisition PurchaseRequisitionItem )
WITH VALUE #( ( %cid_ref = lv_cid_po_hdr
%target = VALUE #( ( %cid = lv_cid_po_item
Material = <fs_req>-Material
Plant = <fs_req>-Plant
OrderQuantity = <fs_req>-Requestedquantity
PurchaseOrderQuantityUnit = lv_unit
PurchaseRequisition = <fs_req>-Purchaserequisition
PurchaseRequisitionItem = <fs_req>-Purchaserequisitionitem ) ) ) )
MAPPED DATA(lt_po_mapped)
FAILED DATA(lt_po_failed)
REPORTED DATA(lt_po_reported).
" keep the ROOT %pid, not the item %pid
IF lt_po_failed IS INITIAL.
APPEND VALUE #( pid = lt_po_mapped-purchaseorder[ 1 ]-%pid
cid = lv_cid_po_hdr
req_uuid = <fs_req>-ReqUuid ) TO zbp_i_pr_request=>purchase_order_details.
ENDIF.And in save_modified, same as your PR loop:
LOOP AT zbp_i_pr_request=>purchase_order_details INTO DATA(ls_po) WHERE pid IS NOT INITIAL.
CONVERT KEY OF i_purchaseordertp_2 FROM ls_po-pid TO DATA(ls_po_key).
" ls_po_key-PurchaseOrder -> update your Z table (PO number + Supplier)
ENDLOOP.Where it usually breaks
Because R_PurchaseOrderTP is strict ( 2 ), a contract violation in the calling code becomes a BEHAVIOR_CONTRACT_VIOLATION dump instead of a message. The reasons that apply here (texts from SNAPT):
CONVERT KEY OF i_purchaseordertp_2, or converting after the PO save failed.Two more things to check:
If it still fails, could you share the exact error: the runtime error name and the reason line from ST22, or the content of FAILED / REPORTED after the MODIFY? Then we can narrow it down.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 12 | |
| 9 | |
| 7 | |
| 6 | |
| 5 | |
| 4 | |
| 3 | |
| 3 | |
| 2 | |
| 2 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.