Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Pramod_Hiremath2
Explorer
3,551

Hello, Everyone 

I am happy to share my very first blog post on SAP RAP (Restful Application Programming) Unmanaged Scenario example using Sales Order Document Business Object.  

Unmanaged scenario, we have more control over the CRUD operations and need to implement them yourself. This allows for more complex business logic and custom processing. 

Unmanaged Implementation Details
Pramod_Hiremath2_0-1721367576687.png

 

Key Aspects of Unmanaged SAP RAP 

  1. Custom Logic 
  • In unmanaged RAP, developers have the flexibility to write their own custom logic for data operations. 
  • This allows for complex business rules and unique processing requirements. 
  •  Implementing specific validation rules for sales orders before they persisted.  
  1. Direct Database Access 
  • Developers can directly access database tables and define data models using CDS views or ABAP classes. 
  • Provides greater control over data structure and retrieval methods. 
  • Creating a custom CDS view for a Sales Order table that joins with Customer and Product tables for comprehensive reporting. 
  1. Explicit Service Definition 
  • Service definitions and behaviors need to be explicitly defined by the developer. 
  • Allows customization of the service layer to fit specific needs. 
  • Manually defining the OData service for handling Sales Order CRUD operations. 
  1. Manual CRUD Operations 
  • CRUD operations (Create, Read, Update, Delete) are explicitly implemented by the developer. 
  • Full control over data management and business logic implementation. 
  • Writing custom methods for creating, updating, and deleting sales orders in the database. 
  1. Integration with Existing Systems 
  • Unmanaged RAP is suitable for scenarios requiring integration with existing systems. 
  • Facilitates the incorporation of legacy systems and complex workflows. 
  • Integrating a Sales Order application with an existing ERP system that has specific APIs and data handling requirements. 
  1. Flexibility 
  • Developers have the freedom to implement complex validation rules, authorization checks, and other custom requirements. 
  • Ensures that all specific business needs are met directly in the application logic. 
  • Adding multi-level approval processes for high-value sales orders within the application. 

Let's walk through a basic example of implementing an unmanaged scenario for a Sales Order Business Object. 
Pramod_Hiremath2_1-1721367631758.png

 

Implementation Overview of Control 

Pramod_Hiremath2_2-1721367631760.png

  Note: Connected ADT to Cloud this Example Completely Cloud Base. 
            Created custom Package ZPSH_RAP_P. 

Create Database table and add fields 
Sales order Header Table ‘ZVBAK_02’ 

 

 

@EndUserText.label : 'Table for Sales Header' 
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 
@AbapCatalog.tableCategory : #TRANSPARENT 
@AbapCatalog.deliveryClass : #A 
@AbapCatalog.dataMaintenance : #RESTRICTED 
define table zvbak_02 { 

key mandt : abap.clnt not null; 
key vbeln : zvbeln_va_01 not null; 
@EndUserText.label : 'Date Created' 
erdat : abap.dats; 
@EndUserText.label : 'Created By' 
ernam : abap.char(12); 
@EndUserText.label : 'Org' 
vkorg : abap.char(4); 
@EndUserText.label : 'Distribution' 
vtweg : abap.char(2); 
@EndUserText.label : 'Division' 
spart : abap.char(2); 
@EndUserText.label : 'Price' 
@Semantics.amount.currencyCode : 'zvbak_01.waerk' 
netwr : abap.curr(13,2); 
@EndUserText.label : 'Currency' 
waerk : abap.cuky; 
@EndUserText.label : 'Billing Block' 
faksk : abap.char(2); 
last_changed_timestamp : timestampl; 
} 

 

 

Sales order Item table ‘ZVBAP_02’ 

 

 

@EndUserText.label : 'Sales Order Item Table' 
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 
@AbapCatalog.tableCategory : #TRANSPARENT 
@AbapCatalog.deliveryClass : #A 
@AbapCatalog.dataMaintenance : #RESTRICTED 
define table zvbap_02 
{ 
key mandt : mandt not null; 
@AbapCatalog.foreignKey.screenCheck : false 
key vbeln : zvbeln_va_01 not null 
with foreign key [1..*,1] zvbak_02 
where mandt = zvbap_02.mandt 
and vbeln = zvbap_02.vbeln; 
@EndUserText.label : 'Item' 
key posnr : abap.numc(6) not null; 
@EndUserText.label : 'Material Number' 
matnr : abap.char(18); 
@EndUserText.label : 'Description' 
arktx : abap.char(40); 
@EndUserText.label : 'Unit Price' 
@Semantics.amount.currencyCode : 'zvbap_02.waerk' 
netpr : abap.curr(13,2); 
@EndUserText.label : 'Total item Price' 
@Semantics.amount.currencyCode : 'zvbap_02.waerk' 
netwr : abap.curr(13,2); 
@EndUserText.label : 'Currency' 
waerk : abap.cuky; 
@EndUserText.label : 'Quantity' 
@Semantics.quantity.unitOfMeasure : 'zvbap_02.kmein' 
kpein : abap.quan(13,2); 
@EndUserText.label : 'Unit' 
kmein : abap.unit(3); 
last_changed_timestamp : timestampl; 
} 

 

 

Insert Data
Create class for inserting data to item table   
Click on Package->New -> ABAP Class -> Class name & Description -> Finish

Pramod_Hiremath2_0-1721368432199.png

Below code for Inserting data to a table using Class and method.

 

 

CLASS zcl_pah_demo_data_02_ DEFINITION 
PUBLIC 
FINAL 
CREATE PUBLIC . 
PUBLIC SECTION. 

INTERFACES if_oo_adt_classrun. 

PRIVATE SECTION. 
METHODS create_sample_so_header. 
METHODS create_sample_so_item. 
METHODS reset_sample_so_item. 
ENDCLASS. 
CLASS zcl_pah_demo_data_02_ IMPLEMENTATION. 
METHOD create_sample_so_header. 
DATA: lt_so_header TYPE STANDARD TABLE OF zvbak_02, 
lv_timestamp TYPE timestampl. 
GET TIME STAMP FIELD lv_timestamp. 
lt_so_header = VALUE #( 
( vbeln = '1001' 
erdat = sy-datum 
ernam = 'Alex' 
vkorg = '1000' 
vtweg = '10' 
spart = '10' 
netwr = '2000.00' 
waerk = 'EUR' 
faksk = '' 
last_changed_timestamp = lv_timestamp ) 
( vbeln = '1002' 
erdat = sy-datum 
ernam = 'Alex' 
vkorg = '1000' 
vtweg = '10' 
spart = '10' 
netwr = '2000.00' 
waerk = 'EUR' 
faksk = '' 
last_changed_timestamp = lv_timestamp ) 
). 
INSERT zvbak_02 FROM TABLE _so_header. 
ENDMETHOD. 
METHOD create_sample_so_item. 
DATA : lt_so_item TYPE TABLE OF zvbap_02, 
lv_timestamp TYPE timestampl. 
GET TIME STAMP FIELD lv_timestamp. 
lt_so_item = VALUE #( 
( 
vbeln = '1001' 
posnr = '10' 
matnr = 'M-10' 
arktx = 'Laptop' 
netpr = '1000' 
netwr = '1000' 
waerk = 'EUR' 
kpein = '1' 
kmein = 'PC' 
last_changed_timestamp = lv_timestamp ) 
( 
vbeln = '1001' 
posnr = '20' 
matnr = 'M-20' 
arktx = 'Office Phone' 
netpr = '1000' 
netwr = '1000' 
waerk = 'EUR' 
kpein = '1' 
kmein = 'PC' 
last_changed_timestamp = lv_timestamp ) 
( 
vbeln = '1002' 
posnr = '10' 
matnr = 'A-20' 
arktx = 'Big Office Desk' 
netpr = '1000' 
netwr = '1000' 
waerk = 'EUR' 
kpein = '1' 
kmein = 'PC' 
last_changed_timestamp = lv_timestamp ) 
). 
INSERT zvbap_02 FROM TABLE _so_item. 
ENDMETHOD. 
METHOD reset_sample_so_item. 
DELETE FROM zvbak_02. 
DELETE FROM zvbap_02. 
ENDMETHOD. 
METHOD if_oo_adt_classrun~main. 
create_sample_so_header( ). 
create_sample_so_item( ). 
IF sy-subrc EQ 0. 
out->write( 
EXPORTING 
data = 'Data Written Done' 
). 
ENDIF. 
ENDMETHOD.
ENDCLASS. 

 

 

 

Header table Records 

Pramod_Hiremath2_1-1721368721009.png

Item Table Record 

Pramod_Hiremath2_2-1721368721012.png

Create the Basic CDS Views For Header and Item table.
Right Click on Package->New->Other ABAP Repository Object -> Data Definition 
Give Basic CDS View Name ‘Z_I_sales_Header_02’ & Description -> Next ->Finish. 

Pramod_Hiremath2_3-1721368773803.png

Sales Header Basic View 

 

 

@AbapCatalog.sqlViewName: 'ZISOHEAD_2' 
@AbapCatalog.compiler.compareFilter: true 
@AbapCatalog.preserveKey: true 
@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'Basic View of Sales Header' 
@ObjectModel.representativeKey: 'sales_doc_num' 
@ObjectModel.semanticKey: [ 'sales_doc_num' ] 
define view Z_I_Sales_header_02 as select from zvbak_02 
association [0..*] to Z_I_Sales_Header_01 as _sd_item_02 
on $projection.sales_doc_num = _sd_item_02.sales_doc_num 
{ 
key vbeln as sales_doc_num, 
erdat as date_created, 
@Semantics.user.createdBy: true 
ernam as person_created, 
vkorg as sales_org, 
vtweg as sales_dist, 
spart as sales_div, 
@Semantics.amount.currencyCode: 'cost_currency' 
netwr as total_cost, 
waerk as cost_currency, 
faksk as block_status, 
@Semantics.systemDateTime.lastChangedAt: true 
last_changed_timestamp as last_changed, 
_sd_item_02 
}  

 

 

 

Sales order Item Basic View

 

 

@AbapCatalog.sqlViewName: 'ZISOITEM_2' 
@AbapCatalog.compiler.compareFilter: true 
@AbapCatalog.preserveKey: true 
@AccessControl.authorizationCheck: #NOT_REQUIRED 
@EndUserText.label: 'Basic View of Sales Item' 
define view Z_I_Sales_item_02 as select from zvbap_02 
association [1..1] to Z_I_Sales_Header_02 as _sd_head_02 
on $projection.sales_doc_num = _sd_head_02.sales_doc_num 
{ 
@ObjectModel.foreignKey.association: '_sd_head_02' 
key vbeln as sales_doc_num, 
key posnr as item_position, 
matnr as mat_num, 
@Semantics.text: true 
arktx as mat_desc, 
@Semantics.amount.currencyCode: 'cost_currency' 
netpr as unit_cost, 
@Semantics.amount.currencyCode: 'cost_currency' 
netwr as total_item_cost, 
@Semantics.currencyCode: true 
waerk as cost_currency, 
@Semantics.quantity.unitOfMeasure: 'unit' 
kpein as quantity, 
@Semantics.unitOfMeasure: true 
kmein as unit, 
@Semantics.systemDateTime.createdAt: true 
last_changed_timestamp as last_changed, 
_sd_head_02 
} 

 

 

   Create Composite Root Views for Header & Item basic views.
Sales Header 

 

 

@AccessControl.authorizationCheck: #NOT_REQUIRED 
@Metadata.allowExtensions: true 
@EndUserText.label: 'Sales Header Root View' 
define root view entity Z_I_Sales_header_U_02 as select from Z_I_Sales_header_02 
composition [0..*] of Z_I_Sales_item_U_02 as _SItemU_02 
{ 
key sales_doc_num, 
date_created, 
person_created, 
sales_org, 
sales_dist, 
sales_div, 
total_cost, 
cost_currency, 
block_status, 
case block_status 
when '' then 'OK' 
when '99' then 'Approval Required' 
else 'Blocked' 
end as block_status_msg, 
last_changed, 
/* Associations */ 
_SItemU_02 
}

 

 

Sales Item 

 

 

@AbapCatalog.sqlViewName: 'ZISOITEM_3' 
@AbapCatalog.preserveKey: true 
@AccessControl.authorizationCheck: #NOT_REQUIRED 
@Metadata.allowExtensions: true 
@EndUserText.label: 'Sales item for managed' 
define view Z_I_Sales_item_U_02 as select from Z_I_Sales_item_02 
association to parent Z_I_Sales_header_U_02 as _SHeadU_02 
on $projection.sales_doc_num = _SHeadU_02.sales_doc_num 
{ 
key sales_doc_num, 
key item_position, 
mat_num, 
mat_desc, 
unit_cost, 
total_item_cost, 
cost_currency, 
quantity, 
unit, 
last_changed, 
_SHeadU_02 
} 

 

 

Create Behavior Definition of Header & Sales root views. 
Behavior Definition defines  

  • What operations (CRUD) are possible for the entities defined.  
  • Whether the operations are managed by SAP or not managed by SAP i.e. unmanaged. Unmanaged operations are then required to be implemented in the associated class.  
  • Additional operations/function imports are also implemented in the associated class.  
  • Read-only fields / Mandatory fields from the service  
  • Field Mapping  

Select the TR and choose Finish to get the below screen. Notice that the behavior is defined for both entities i.e. Sales Header and Sales Item.  

Pramod_Hiremath2_0-1721369922440.png

Complete the definition with the below code and Save and Activate the definition. 

 

 

unmanaged implementation in class zbp_i_sales_header_u_02 unique;
//strict ( 2 );

define behavior for Z_I_Sales_header_U_02 alias SOHeader
//late numbering
//lock master
//authorization master ( instance )
//etag master last_changed
{
  create;
  update(features :instance);
  delete(features :instance);
field (readonly) sales_doc_num, last_changed, date_created, block_status,person_created;
  mapping for zvbak_02 control Z_I_SALES_HEADER_U_02 corresponding
  {
 sales_doc_num = vbeln;
  block_status = faksk;
  sales_dist = vtweg;
  sales_div = spart;
  total_cost = netwr;
  cost_currency = waerk;
  person_created = ernam;
  date_created = erdat;
  last_changed = last_changed_timestamp;
  }

  //field ( readonly ) sales_doc_num;
  association _SItemU_02 { create(features :instance); }
  action blockOrder result[1]$self;
  action UnblockOrder result[1]$self;
}
define behavior for Z_I_Sales_item_U_02 alias SOItem
//late numbering
//lock dependent by _SHeadU_02
//authorization dependent by _SHeadU_02
//etag master <field_name>
{
  create;
  update;
  delete;

  mapping for zvbap_02 control Z_I_SALES_ITEM_U_02 corresponding{
    sales_doc_num = vbeln;
    item_position = posnr;
    cost_currency = waerk;
    mat_desc = arktx;
    mat_num = matnr;
    quantity = kpein;
    total_item_cost = netwr;
    unit_cost = netpr;
    unit = kmein;
    last_changed = last_changed_timestamp;
  }
  //field ( readonly ) sales_doc_num, item_position;
  //association _SHeadU_02;
}

 

 

We Got Warning Here Because we have not created the associated class so far, so let us do that now.   

Pramod_Hiremath2_1-1721370099308.png

The highlighted warning has a quick-fix feature that lets us create a class automatically.

Click on the yellow warning icon and then create the class. Choose the only option that is presented below.  

Pramod_Hiremath2_2-1721370099309.png

Create Service Definition & Service Binding exposing root CDS and Item 

Service Definition  

  • Right click on Sales Header Root View and choose New Service Definition.  
  • Provide Name, Description and validate Type is Definition and reference object is accurate. Choose Next.  
  • Select TR and choose Finish to get below screen.  

Pramod_Hiremath2_3-1721370150582.png

Complete the Service definition with the code below, Save and Activate. 

 

 

@EndUserText.label: 'Sales Header Service Defination'
define service Z_SD_U_02 {
  expose Z_I_Sales_header_U_02;
  expose Z_I_Sales_item_U_02;
}

 

 

Service Binding  

Service Binding is a way to select which version of OData we will use, register the service and then generate the service which can be tested immediately from Eclipse.  

  • Right-click on the service definition Z_SD_U_02 and choose New Service Binding.  
  •  Provide Name, Description, and and Binding Type (OData V2 – UI) and validate the Service Definition. Choose Next.  

Pramod_Hiremath2_4-1721370307838.png

  •  Select TR and choose Finish to get below screen.  
  • This process is the same for Managed / Unmanaged scenarios.  
  •  Activate the Service Binding which then enables the Publish button.  

Pramod_Hiremath2_5-1721370348025.png

Click Publish. This generally takes some time, so wait. Once the Service is published, the status changes to Published, and a review button is enabled that can be used to test. 

Next give the metadata for Sales Header and Sales Item Root views. 

Sales Header 

 

 

@Metadata.layer: #CUSTOMER
@UI: { 
headerInfo:{ 
typeName: 'Sales Document',
typeImageUrl: 'Sales Documents',

title: { type:#STANDARD, label: 'Sales Order', value: 'sales_doc_num' },
description: {  label: 'Date Created', value: 'date_created' }

}
}

annotate view Z_I_Sales_header_U_02
    with 
{
    .facet: [
    { 
    id: 'General', type: #IDENTIFICATION_REFERENCE,
    position: 10, label: 'Sales Document'
    },
    
    { 
    type: #FIELDGROUP_REFERENCE, position: 10, targetQualifier: 'BasicInfo',
    parentId: 'General', isSummary:true, isPartOfPreview: true
    },
    
    { 
    id: 'SItemM_02', purpose: #STANDARD, type: #LINEITEM_REFERENCE,
    label: 'Sales Order Item sample', position: 10, targetElement: '_SItemU_02'
    }    
  ]
@UI: { 
lineItem: [{ position: 10, label: 'Number', importance: #HIGH, targetElement: '_SItemU_02.sales_doc_num'}],
identification: [{ position: 10, label: 'Number' }],
selectionField: [{ position: 10 }],
fieldGroup: [{ qualifier: 'BasicInfo', position: 10, importance: #HIGH }]
}
sales_doc_num;
@UI: {
lineItem: [{ position: 20, label: 'Created On', importance: #HIGH }],
identification: [{ position: 20, label: 'Created On' }],
fieldGroup: [{ qualifier: 'BasicInfo', position: 20, importance: #HIGH }]
}
date_created;
@UI: { 
lineItem: [{ position: 30, label: 'Price', importance: #HIGH }],
fieldGroup: [{ qualifier: 'BasicInfo', position: 30, importance: #HIGH }]
}
total_cost;
@UI: { 
lineItem: [{ position: 40, label: 'Status', importance: #HIGH },
{ type:#FOR_ACTION, dataAction: 'blockOrder', label: 'Block Order' },
{ type:#FOR_ACTION, dataAction: 'UnblockOrder', label: 'Un-Block Order' }],
identification: [{ position: 40, label: 'Status' }],
fieldGroup: [{ qualifier: 'BasicInfo', position: 40, importance: #HIGH }]
}
block_status_msg;
@UI: { 
lineItem: [{ position: 50, label: 'Created By', importance: #HIGH }],
identification: [{ position: 50, label: 'Created By' }],
fieldGroup: [{ qualifier: 'DetailInfo', position: 50, importance: #HIGH }]
}
person_created;
@UI: { 
lineItem: [{ position: 50, label: 'Sales Org', importance: #HIGH }],
identification: [{ position: 50, label: 'Sales Org' }],
fieldGroup: [{ qualifier: 'DetailInfo', position: 60, importance: #HIGH }]
}
sales_org;
@UI: { 
lineItem: [{ position: 50, label: 'Distrubution' }],
identification: [{ position: 50, label: 'Distrubution' }],
fieldGroup: [{ qualifier: 'DetailInfo', position: 70, importance: #HIGH }]
}
sales_dist;
@UI: { 
lineItem: [{ position: 50, label: 'Division' }],
identification: [{ position: 50, label: 'Division' }],
fieldGroup: [{ qualifier: 'DetailInfo', position: 80, importance: #HIGH }]
}
sales_div;
}

 

 

Sales Item 

 

 

@Metadata.layer: #CUSTOMER
annotate view Z_I_Sales_item_U_02
    with 
{
   .facet: [{ 
   type: #IDENTIFICATION_REFERENCE, position: 10, id: 'SItemU_02', label: 'Item'},
   
   { type: #FIELDGROUP_REFERENCE, position: 10, targetQualifier: 'BasicInfo', parentId: 'SItemU_02',
   isSummary:true, isPartOfPreview: true }
   
   ]
 
@UI: { 

lineItem: [{ position: 10, label: 'Number', importance: #HIGH}, { type: #FOR_ACTION,
dataAction: 'CreatedByTemplate', label: 'Created By Template' }],

identification: [{ position: 10, label: 'Number' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 10, importance: #HIGH }]

}
 sales_doc_num; 
 
  : { 

lineItem: [{ position: 20, label: 'Position', importance: #HIGH}],

identification: [{ position: 20, label: 'Position' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 20, importance: #HIGH }]

}
 item_position;
  : { 

lineItem: [{ position: 30, label: 'material', importance: #HIGH}],

identification: [{ position: 30, label: 'material' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 30, importance: #HIGH }]

}
 mat_num;
  : { 

lineItem: [{ position: 40, label: 'Description', importance: #HIGH}],
identification: [{ position: 40, label: 'Description' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 40, importance: #HIGH }]

}
 mat_desc;
  : { 

lineItem: [{ position: 50, label: 'Quantity', importance: #HIGH}],

identification: [{ position: 50, label: 'Quantity' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 50, importance: #HIGH }]

}
 quantity;
 : { 

lineItem: [{ position: 60, label: 'Unit Price', importance: #HIGH}],

identification: [{ position: 60, label: 'Unit Price' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 60, importance: #HIGH }]

}
 unit_cost;  
 
  : { 

lineItem: [{ position: 70, label: 'Total Price', importance: #HIGH}],

identification: [{ position: 70, label: 'Total Price' }],
fieldGroup: [{ qualifier: 'ItemDetail', position: 70, importance: #HIGH }]

}
 total_item_cost;
}
 

 

 

Pramod_Hiremath2_6-1721371405402.png

Note : In header annotation add metadata extension Annotation. 
@Metadata.allowExtensions: true 

Pramod_Hiremath2_7-1721371459536.png

Test the Service

Pramod_Hiremath2_8-1721371530492.png

Pramod_Hiremath2_9-1721371578460.png

Pramod_Hiremath2_10-1721371602674.png

CRUD OPERATIONS

CREATE Operation
Inserting Record Along with Some Fields Won’t Take Values from User Hide Those Fields. 

 

 

field (readonly) sales_doc_num, last_changed, date_created, block_status,person_created; 

 

 

Pramod_Hiremath2_11-1721371716569.png

Sales Document Number Auto Generation Code. 

 

 

DATA:ls_so_head TYPE ZVBAK_02, 

lt_so_head TYPE TABLE OF ZVBAK_02, 

lv_old_max_vbeln TYPE ZVBAK_02-vbeln, 

lv_temp_vbeln TYPE i,"For convert Type 

ls_timestamp TYPE timestampl. 

 

"New sales Document Number calculate and Generate 
lv_temp_vbeln = CONV i( lv_old_max_vbeln ) + 1."Convert the integer and Increment the value 

ls_so_head-vbeln = CONV ZVBELN_VA_01( lv_temp_vbeln ). "after increment again convert to the Type 

CONDENSE ls_so_head-vbeln. 

lv_old_max_vbeln = lv_old_max_vbeln + 1.

 

 

Implement the Create Method in Sales Header Class 

Pramod_Hiremath2_12-1721371794120.png

Operation Class->Local Class (For Buffer) 
Declare and implement Method in Buffer 

 

 

METHODS : buffer_so_header_create IMPORTING it_so TYPE tt_tables_soh. "Declaration


//Implementation
METHOD buffer_so_header_create. 
MOVE-CORRESPONDING it_so to tsoh_create. 
ENDMETHOD. 

 

 

Implement Save method. 

 

 

METHOD save. 
INSERT zvbak_02 FROM TABLE @( tsoh_create ). 
ENDMETHOD. 

 

 

Global Operation class need to Declare and implement with call the instance. 

 

 

//Declaration
METHODS : buffer_so_header_create IMPORTING it_so TYPE tt_tables_SOH. 

//Implementation
METHOD buffer_so_header_create. 
lcl_so_buffer=>get_instance( )->buffer_so_header_create( EXPORTING it_so = it_so ). 
ENDMETHOD. 

 

 

Clear Buffer After Insert data. 

 

 

METHOD clear. 
CLEAR : 
tsoh_create. 
ENDMETHOD. 

 

 

In Preview Click on create

Pramod_Hiremath2_13-1721372038542.png

Give values For Fields->Click on Create button 

Pramod_Hiremath2_14-1721372079012.png

Pramod_Hiremath2_15-1721372104195.png

Pramod_Hiremath2_16-1721372118901.png

 

UPDATE Operation

Create Custom Interface for Defining the structure for sales document. 

Pramod_Hiremath2_17-1721372164452.png

Pramod_Hiremath2_18-1721372215147.png

In Behavior Implementation Local class, we need to define methods.

 

 

METHOD update. 
DATA:ls_so_head TYPE ZVBAK_02, 
lt_po_head TYPE STANDARD TABLE OF ZVBAK_02, 
ls_so_control TYPE zif_so_structure1=>ts_so_control,"for line item 
lt_so_control TYPE zif_so_structure1=>tt_so_control, 
lv_timestamp TYPE timestampl. 
 
LOOP AT entities ASSIGNING FIELD-SYMBOL(<fs_so_head>). 
ls_so_head = CORRESPONDING #( <fs_so_head> MAPPING 
vbeln = sales_doc_num 
faksk = block_status 
vtweg = sales_dist 
spart = sales_div 
vkorg = sales_org 
netwr = total_cost 
waerk = cost_currency 
ernam = person_created 
erdat = date_created ). 
ls_so_head-last_changed_timestamp = lv_timestamp. 
APPEND ls_so_head to lt_po_head.
 
ls_so_control = CORRESPONDING #( <fs_so_head>-%control MAPPING 
vbeln = sales_doc_num 
faksk = block_status 
vtweg = sales_dist 
spart = sales_div 
vkorg = sales_org 
netwr = total_cost 
waerk = cost_currency 
ernam = person_created 
erdat = date_created ). 
ls_so_control-vbeln_id = ls_so_head-vbeln. 
APPEND ls_so_control to lt_so_control. 
ENDLOOP. 

zcl_so_operation_u_02=>get_instance( )->buffer_so_header_update( EXPORTING it_so = lt_po_head 
it_so_control = lt_so_control ). 
ENDMETHOD. 

 

 

In Operation Buffer Class Define the update buffer method.

 

 

METHODS : buffer_so_header_update IMPORTING it_so TYPE tt_tables_soh 
it_so_control TYPE ZIF_SO_STRUCTURE1=>tt_so_control. 

 

 

Implement the update buffer Method.

 

 

METHOD buffer_so_header_update. 
 
" Declarations 
DATA: lv_flag_control TYPE i VALUE 2, " Counter for component index 
lr_structure_desc TYPE REF TO cl_abap_structdescr, " Reference to structure descriptor 
lt_structure_desc TYPE ABAP_COMPONENT_TAB, " Table to hold structure components 
l_component TYPE LINE OF ABAP_COMPONENT_TAB, " Line type for structure components 
lv_new_timestamp TYPE timestampl. " Timestamp variable 
 
" Get current timestamp 
GET TIME STAMP FIELD lv_new_timestamp. 

" Select data from ZVBAK_02 for all entries in input table it_so 
SELECT * FROM ZVBAK_02 
FOR ALL ENTRIES IN _so 
WHERE vbeln = _so-vbeln INTO TABLE (lt_so_data_all). 
 
" Loop through selected data 
LOOP AT lt_so_data_all ASSIGNING FIELD-SYMBOL(<fs_so_line>). 
 
" Read corresponding entry from input table it_so using vbeln as key 
READ TABLE it_so ASSIGNING FIELD-SYMBOL(<fs_ls_so_new>) WITH KEY vbeln = <fs_so_line>-vbeln. 
IF SY-subcs = 0. " Check if read was successful 
 
" Read corresponding entry from it_so_control using vbeln_id as key 
READ TABLE it_so_control ASSIGNING FIELD-SYMBOL(<fs_so_control>) WITH KEY vbeln_id = <fs_so_line>-vbeln.  
" Describe structure components if not already done 
IF lt_structure_desc IS INITIAL. 
lr_structure_desc ?= cl_abap_typedescr=>describe_by_data( <fs_so_control> ). 
lt_structure_desc = lr_structure_desc->get_components( ). 
ENDIF. 

DO. 
" Assign flag_control component dynamically 
ASSIGN COMPONENT lv_flag_control OF STRUCTURE <fs_so_control> TO FIELD-SYMBOL(<v_flag>). 
IF sy-subrc <> 0. " If component does not exist, exit loop 
EXIT. 
ENDIF. 
" Check flag value and update if necessary 
IF <v_flag> EQ '01' OR <v_flag> EQ '1'. 
" Read structure component from lt_structure_desc using flag_control index 
READ TABLE lt_structure_desc INTO l_component INDEX lv_flag_control. 
" Assign corresponding components of fs_so_line and fs_ls_so_new 
ASSIGN COMPONENT l_component-name OF STRUCTURE <fs_so_line> TO FIELD-SYMBOL(<fs_db_data>). 
ASSIGN COMPONENT l_component-name OF STRUCTURE <fs_ls_so_new> TO FIELD-SYMBOL(<fs_updated>). 
" Update data in fs_so_line from fs_ls_so_new and set timestamp 
<fs_db_data> = <fs_updated>. 
<fs_so_line>-last_changed_timestamp = lv_new_timestamp. 
ENDIF. 
" Increment flag_control for next component 
lv_flag_control = lv_flag_control + 1. 
ENDDO. 
ENDIF. 
" Append updated fs_so_line to output table tSOH_Update 
APPEND <fs_so_line> TO tSOH_Update. 
ENDLOOP. 
ENDMETHOD. 

 

 

In Save Method

 

 

METHOD save. 
UPDATE ZVBAK_02 FROM TABLE @( tSOH_Update ). 
ENDMETHOD. 

 

 

Output UPDATE Operation 

Select Header Record-> Click on Edit Button 

Pramod_Hiremath2_19-1721372550065.png

Change the Values and click on save button 

Pramod_Hiremath2_20-1721372575803.png

Pramod_Hiremath2_21-1721372591406.png

DELETE Operations

Pramod_Hiremath2_22-1721372632674.png

Operation Class 

 

 

//Saver Class Control we have logic called save with in the save calling the //local save Local save need to have SQL code. 

METHOD save. 
zcl_so_operation_u_02=>get_instance( )->save( ). 
ENDMETHOD. 

 

 

Operation Class -> Local class 

 

 

METHOD clear. 
CLEAR : tSOH_Update,
tSOH_delete, //Clear the header buffer 
tSOI_delete. //Clear the item buffer 
ENDMETHOD. 

 

 

Accordingly  Remove entries from the header and item table which are stored in 'TSOH_DELETE & TSOI_DELETE' Buffer.

 

 

METHOD save. 
DELETE zvbak_02 FROM TABLE @( CORRESPONDING #( tsoh_delete ) ). 
DELETE zvbak_02 FROM TABLE @( CORRESPONDING #( tsoi_delete ) )."item buffer 
ENDMETHOD. 

 

 

We have to Cleanup we will reset value after deleting the record from table and we should cleanup the Buffer. 

 

 

METHOD cleanup. 
zcl_so_operation_u_02=>get_instance( )->clear( ). 
ENDMETHOD. 

 

 

PUT Debugger on Delete SQL Statement

Pramod_Hiremath2_23-1721372885037.png

Go to Preview Select Record -> Click Delete Button

Pramod_Hiremath2_24-1721372913215.png

Pramod_Hiremath2_25-1721372929734.png

Output Record deleted

Pramod_Hiremath2_26-1721372956867.png

After Deleted Only One Record Left in Table

Pramod_Hiremath2_27-1721372972652.png

 

Actions

Requirement is needed to do block the sales order and unblock based on approval request. 
In Behavior Definition we must declare required actions “Block Order” & “Unblock Order” 

Pramod_Hiremath2_28-1721373082113.png

In Operation class->local types and global Need to Declare method for Block and unblock Operation. 

 

 

METHODS buffer_so_block_ublock IMPORTING it_so TYPE tt_tables_SOH 
lv_block TYPE ZVBAK_02-faksk. 

 

 

Implement the Method in local type. 

 

 

METHOD buffer_so_block_ublock. 
SELECT * FROM ZVBAK_02 
FOR ALL ENTRIES IN _so 
WHERE vbeln = _so-vbeln INTO TABLE (lt_so). 
LOOP AT lt_so ASSIGNING FIELD-SYMBOL(<fs_so>). 
<fs_so>-faksk = lv_block. 
APPEND <fs_so> TO tSOH_Update. 
ENDLOOP. 
ENDMETHOD. 

 

 

In Global operation class call the method. 

 

 

METHOD buffer_so_block_ublock. 
lcl_so_buffer=>get_instance( )->buffer_so_block_ublock( EXPORTING it_so = it_so 
lv_block = lv_block ). 
ENDMETHOD. 

 

 

Declare Methods in Sales header class. 

 

 

DATA: block_code TYPE ZVBAK_02-faksk VALUE '99', “Constants 
unblock_code TYPE ZVBAK_02-faksk VALUE ''. 

METHODS blockOrder FOR MODIFY 
IMPORTING keys FOR ACTION SOHeader~blockOrder RESULT result. 
 

METHODS UnblockOrder FOR MODIFY 
IMPORTING keys FOR ACTION SOHeader~UnblockOrder RESULT result. 

 

 

Implement the methods. 

 

 

METHOD blockOrder. 
DATA:ls_so TYPE ZVBAK_02, 
lt_so TYPE STANDARD TABLE OF ZVBAK_02. 
 
LOOP AT keys ASSIGNING FIELD-SYMBOL(<fs_so>). 
ls_so-vbeln = <fs_so>-sales_doc_num. 
ls_so-faksk = block_code. 
 
APPEND ls_so TO lt_so. 
ENDLOOP. 
zcl_so_operation_u_02=>get_instance( )->buffer_so_block_ublock( EXPORTING it_so = lt_so 
lv_block = block_code ). 
result = value #( for ls_so_temp IN lt_so ( sales_doc_num = ls_so_temp-vbeln 
%param-sales_doc_num = ls_so_temp-vbeln 
%param-block_status = ls_so_temp-faksk ) ). 
 
ENDMETHOD. 
 
 
METHOD UnblockOrder. 
DATA:ls_so TYPE ZVBAK_02, 
lt_so TYPE STANDARD TABLE OF ZVBAK_02. 
 
LOOP AT keys ASSIGNING FIELD-SYMBOL(<fs_so>). 
ls_so-vbeln = <fs_so>-sales_doc_num. 
ls_so-faksk = unblock_code. 

APPEND ls_so TO lt_so. 
ENDLOOP. 
zcl_so_operation_u_02=>get_instance( )->buffer_so_block_ublock( EXPORTING it_so = lt_so 
lv_block = unblock_code ). 
result = value #( for ls_so_temp IN lt_so ( sales_doc_num = ls_so_temp-vbeln 
%param-sales_doc_num = ls_so_temp-vbeln 
%param-block_status = ls_so_temp-faksk ) ). 
ENDMETHOD. 

 

 

Preview
Select the sales documents and click on the block order action button. 

Pramod_Hiremath2_29-1721373413339.png

Selected sales orders are blocked status will change after clicking blocked. 
Pramod_Hiremath2_30-1721373442168.png

Select blocked Sales order and click on unblocked action button. 

Pramod_Hiremath2_31-1721373478533.png

Unblocked sales order documents are status will change after unblocking. 

Pramod_Hiremath2_32-1721373506401.png

Instance Feature

Using the instance feature, we can prevent the creation or updating of a particular sales document if it has been blocked.

Pramod_Hiremath2_33-1721373554477.png

Add the methods in sales header class. 

 

 

METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR SOHeader RESULT result. 

 

 

Implement the methods for instance feature. 

 

 

METHOD get_instance_features. 
DATA: lt_result LIKE LINE OF result. 
 
SELECT * FROM ZVBAK_02 FOR ALL ENTRIES IN @keys 
WHERE vbeln = @keys-sales_doc_num INTO TABLE (lt_so). 
 
LOOP AT lt_so ASSIGNING FIELD-SYMBOL(<fs_so>). 
lt_result = VALUE #( sales_doc_num = <fs_so>-vbeln 

%update = COND #( WHEN <fs_so>-faksk = '' 
THEN if_abap_behv=>fc-f-unrestricted 
ELSE if_abap_behv=>fc-f-read_only ) 

%delete = COND #( WHEN <fs_so>-faksk = '' 
THEN if_abap_behv=>fc-f-unrestricted 
ELSE if_abap_behv=>fc-f-read_only ) 

%assoc-_SItemU_02 = COND #( WHEN <fs_so>-faksk = '' 
THEN if_abap_behv=>fc-f-unrestricted 
ELSE if_abap_behv=>fc-f-read_only ) 
). 
APPEND lt_result to result. 
ENDLOOP. 
ENDMETHOD. 

 

 

 

 

 

 

 

3 Comments
Anoop_L
Explorer

Proper Content, Period!

qiujiaoyao
Explorer
0 Kudos

  Very good case, I am referring to your example for practice

I found this class ZCL_SO_OPERATION_U_02, can you provide the complete code? I have been looking at the curve part for a long time and it is not very complete. Can you provide the complete code of the curve

 

bygineben
Explorer
0 Kudos

Hi,

Thanks for sharing. However, Since Define View systax is obsolete as of AS ABAP 7.57, It's better to use Define View Entity / Define Root View Entity. Which S/4 HANA version are you using?

Labels in this area