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
Key Aspects of Unmanaged SAP RAP
Let's walk through a basic example of implementing an unmanaged scenario for a Sales Order Business Object.
Implementation Overview of Control
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
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
Item Table Record
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.
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
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.
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.
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.
Create Service Definition & Service Binding exposing root CDS and Item
Service Definition
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.
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;
}
Note : In header annotation add metadata extension Annotation.
@Metadata.allowExtensions: true
Test the Service
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;
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
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
Give values For Fields->Click on Create button
UPDATE Operation
Create Custom Interface for Defining the structure for sales document.
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
Change the Values and click on save button
DELETE Operations
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
Go to Preview Select Record -> Click Delete Button
Output Record deleted
After Deleted Only One Record Left in Table
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”
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.
Selected sales orders are blocked status will change after clicking blocked.
Select blocked Sales order and click on unblocked action button.
Unblocked sales order documents are status will change after unblocking.
Instance Feature
Using the instance feature, we can prevent the creation or updating of a particular sales document if it has been blocked.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
5 | |
5 | |
4 | |
3 | |
3 | |
2 | |
2 | |
2 | |
2 | |
2 |