You are on page 1of 70

This document is for BOPF beginners .

This
document has step by step information with
screen shots on how to create BOPF
application.

Disclaimer: No part of this publication may


be reproduced or transmitted in any form
or for any purpose without the express
2015
permission of SAP SE.This is for SAP internal
use only.

SAP BOPF Exercise

Ankush Jain & Abhishek Kumar


SAP Internal
1/21/2015
Table of Contents
Creating a BO ................................................................................................................................................ 2
Exercise 1 Create Invoice ................................................................................................................... 16
Query Creation ............................................................................................................................................ 17
Exercise 2: Query Invoice Instances ........................................................................................................ 24
Exercise 3: Retrieve Invoice Items by Association .................................................................................. 25
Creation of Action ....................................................................................................................................... 26
Creation of Determination .......................................................................................................................... 29
Creation of Validation ................................................................................................................................. 32
Create Consistency Validation .................................................................................................................... 37
Creation of Alternative Keys. ...................................................................................................................... 42
Exercise 4: Convert Invoice ID ................................................................................................................. 46
Exercise 5: Update All Invoice Instances. ................................................................................................ 47
Exercise 7: Delete All Invoices ................................................................................................................. 48
Exercise 8: Check Invoice Consistency .................................................................................................... 49
Advance Topics ........................................................................................................................................... 50
Properties................................................................................................................................................ 50
Static Properties .................................................................................................................................. 50
Dynamic Properties ............................................................................................................................. 51
Special Associations ................................................................................................................................ 55
Advance Feature ..................................................................................................................................... 59
Late Numbering .................................................................................................................................. 59
Creating a BO
1. Create a domain ZCI_11_PAYMENT_STATUS Choose Data Type = CHAR and
No. Characters = 2. Enter the Fixed Values 01 with description Not Paid and 02 with
description Invoice Paid.
2. Create a data element ZCI_11_PAYMENT_STATUS that uses the domain ZCI_
11_PAYMENT_STATUS.

3. create a structure ZCI_11_S_ROOT_D having two components, INVOICE_ID (type INT4)


and PAYMENT_STATUS (type ZCI_11_PAYMENT_STATUS).
4. Open Transaction /BOBF/CONF_UI AND Choose create business object and create a
Business Object that is named ZCI_11_CUSTOMER_INVOICE . Enter the prefix ZCI_11
on tab Business Object. The root node is created automatically with the business
object. Select Object Category as Business process Object .
5. Navigate to the ROOT node and use the Propose Repository Names function to
propose names for the combined table type, combined structure, data structure, and
database table. Change the data structure name to ZCI_11_S_ROOT_D.
Path : Extras->Propose Repository Names .
6. Create a new node below the ROOT node named ITEM.
7. Go to the Propose Repository Names function to propose names for the combined
table type, combined structure, data structure, and database table.
8. Use forward navigation to create the data structure ( ZCI_11_S_ITEM_D) including a
reasonable set of fields (ITEM_ID (type INT4), PRICE (type INT4), CURRENCY (type
WAERS), QUANTITY (type INT4), AMOUNT (type INT4)). Note that you can add additional
fields at any time later on. Activate the data structure in DDIC and go back to BOPF.
9. Use the Generate Dictionary Elements function to generate corresponding structures
and tables for the combined structures and tables as well as the database tables.
Gotp Extras -> Generate Repository Names-> Generate Constant Interface.
10. Go to the Test UI (F8) and check how the business object is doing.

Enter The Root Value


Enter ITEM detail

Save Transaction.
Exercise 1 Create Invoice
Create report ZCI_11_CREATE_INVOICE (transaction se38). It shall create new invoices with ID 123.
Finally, save the transaction and Execute the Report.
REPORT ZCI_11_CREATE_INVOICE.

" get the service manager of the Invoice BO


DATA lo_customer_invoice TYPE REF TO /bobf/if_tra_service_manager.
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = ZIF_CI_11_CUSTOMER_INVOICE_C=>sc_bo_key ).
" create a new invoice with ID 123
DATA lt_modification TYPE /bobf/t_frw_modification.
DATA ls_modification TYPE /bobf/s_frw_modification.
DATA ls_ref_root_data TYPE REF TO zci_11_s_root.
CREATE DATA ls_ref_root_data.
ls_modification-node = zif_ci_11_customer_invoice_c=>sc_node-root.
ls_modification-change_mode = /bobf/if_frw_c=>sc_modify_create.
ls_modification-key = lo_customer_invoice->get_new_key( ).
ls_modification-data = ls_ref_root_data.
ls_ref_root_data->invoice_id = '123'.
APPEND ls_modification TO lt_modification.
" execute modification
DATA lo_change TYPE REF TO /bobf/if_tra_change.
lo_customer_invoice->modify(
EXPORTING it_modification = lt_modification
IMPORTING eo_change = lo_change ).
" check if the instance has been successfully created
IF lo_change->has_failed_changes( ) = abap_true. BREAK-POINT. ENDIF.
" save the transaction
DATA lo_transaction_manager TYPE REF TO /bobf/if_tra_transaction_mgr.
lo_transaction_manager = /bobf/cl_tra_trans_mgr_factory=>get_transaction_mana
ger( ).
lo_transaction_manager->save( ).
Query Creation
1. Right click on Query node and select Create Query. Provide the Name of Query as
SELECT_ALL.
2. Go to Extras->Propose Repository object
3. Create Structure for the Result in SE11.
4. Create Table Type for the Structure.

5. Goto Query Class ZCL_CI_11_Q_SELECT_ALL and Redefine Method


/BOBF/IF_FRW_QUERY~QUERY and Write the Below Code.

DATA: ls_key TYPE /bobf/s_frw_key,


lt_selection TYPE /bobf/t_frw_query_selparam,
ls_selection TYPE REF TO /bobf/s_frw_query_selparam,
ls_sorting TYPE /bobf/s_frw_query_sorting,
lv_index TYPE i,
lv_max_rows TYPE i,
lv_where TYPE string,
lt_where TYPE STANDARD TABLE OF string,
lv_order TYPE string,
lt_order TYPE STANDARD TABLE OF string,
lt_range_key TYPE RANGE OF /bobf/conf_key,
ls_range_key LIKE LINE OF lt_range_key,
ls_comp TYPE cl_abap_structdescr=>component,
lt_comp TYPE cl_abap_structdescr=>component_table,
ls_range_r TYPE REF TO data,
lo_range TYPE REF TO cl_abap_structdescr,
lt_range TYPE RANGE OF string, "#EC NEEDED
ls_range LIKE LINE OF lt_range,
lt_result_db TYPE STANDARD TABLE OF ZCI_11_D_ROOT,
ls_result TYPE ZCI_11_S_Q_SELECT_ALL,
lt_result TYPE ZCI_11_T_Q_SELECT_ALL,
lx_root TYPE REF TO cx_root.

FIELD-SYMBOLS: <ls_result_db> TYPE ZCI_11_D_ROOT,


<ls_range> TYPE any,
<lt_range> LIKE lt_range.

CLEAR: et_key, et_data, es_query_info.


* build where condition for key filter
IF it_filter_key IS NOT INITIAL.
LOOP AT it_filter_key INTO ls_key.
ls_range_key-option = 'EQ'. ls_range_key-sign = 'I'. ls_range_key-
low = ls_key-key. INSERT ls_range_key INTO TABLE lt_range_key.
ENDLOOP.
lv_where = 'DB_KEY IN LT_RANGE_KEY'.
APPEND lv_where TO lt_where.
ENDIF.

* build where condition from selection


IF it_selection_parameters IS NOT INITIAL.
lt_selection = it_selection_parameters.
SORT lt_selection BY attribute_name.
LOOP AT lt_selection REFERENCE INTO ls_selection.
AT NEW attribute_name.
ls_comp-name = ls_selection->attribute_name.
ls_comp-type ?= cl_abap_typedescr=>describe_by_data( lt_range ).
APPEND ls_comp TO lt_comp.
ENDAT.
ENDLOOP.

lo_range = cl_abap_structdescr=>create( lt_comp ).


CREATE DATA ls_range_r TYPE HANDLE lo_range.
ASSIGN ls_range_r->* TO <ls_range>.
LOOP AT lt_selection REFERENCE INTO ls_selection.
AT NEW attribute_name.
IF lt_where IS NOT INITIAL.
lv_where = 'AND'.
APPEND lv_where TO lt_where.
ENDIF.
CONCATENATE '<LS_RANGE>-' ls_selection->attribute_name INTO lv_where.
ASSIGN (lv_where) TO <lt_range>.
ENDAT.
MOVE-CORRESPONDING ls_selection->* TO ls_range.
INSERT ls_range INTO TABLE <lt_range>.
AT END OF attribute_name.
IF ls_selection-
>attribute_name = /bobf/if_conf_c=>sc_attribute_name_key.
ls_selection->attribute_name = 'DB_KEY'.
ENDIF.
CONCATENATE ls_selection-
>attribute_name 'IN' lv_where INTO lv_where SEPARATED BY space.
APPEND lv_where TO lt_where.
ENDAT.
ENDLOOP.
ENDIF.
* build order by table
LOOP AT is_query_options-sorting_options INTO ls_sorting.
IF ls_sorting-ascending = abap_true.
CONCATENATE ls_sorting-
attribute_name 'ASCENDING' INTO lv_order SEPARATED BY space.
ELSE.
CONCATENATE ls_sorting-
attribute_name 'DESCENDING' INTO lv_order SEPARATED BY space.
ENDIF.
APPEND lv_order TO lt_order.
ENDLOOP.
* default order if paging is active
IF sy-subrc <> 0 AND is_query_options-paging_options-
paging_active = abap_true.
lv_order = 'DB_KEY ASCENDING'.
APPEND lv_order TO lt_order.
ENDIF.
IF is_query_options-paging_options-
paging_active = abap_true AND is_query_options-paging_options-
start_key IS NOT INITIAL.
IF lt_where IS NOT INITIAL.
lv_where = 'AND'.
APPEND lv_where TO lt_where.
ENDIF.
lv_where = 'DB_KEY GT IS_QUERY_OPTIONS-PAGING_OPTIONS-START_KEY'.
APPEND lv_where TO lt_where.
ENDIF.
IF is_query_options-maximum_rows > 0.
lv_max_rows = is_query_options-maximum_rows.
IF is_query_options-paging_options-
paging_active = abap_true AND is_query_options-paging_options-
start_row IS NOT INITIAL.
lv_max_rows = 0.
ENDIF.
ENDIF.
if IT_SELECTION_PARAMETERS is NOT INITIAL or it_filter_key is NOT INITIAL.
TRY.
SELECT * FROM ZCI_11_D_ROOT UP TO lv_max_rows ROWS INTO CORRESPONDING F
IELDS OF TABLE lt_result_db WHERE (lt_where) ORDER BY (lt_order). "#EC CI_DYN
TAB "#EC CI_DYNWHERE
es_query_info-count = sy-dbcnt.
LOOP AT lt_result_db ASSIGNING <ls_result_db>.
MOVE-CORRESPONDING <ls_result_db> TO ls_result.
ls_result-key = <ls_result_db>-db_key.
INSERT ls_result INTO TABLE lt_result.
ls_key-key = <ls_result_db>-db_key.
INSERT ls_key INTO TABLE et_key.
ENDLOOP.
CATCH cx_sy_sql_error INTO lx_root.
ASSERT ID /bobf/dac CONDITION 0 = 1. RAISE EXCEPTION TYPE /bobf/cx_dac
EXPORTING previous = lx_root mv_node = is_ctx-node_key.
ENDTRY.
else.
TRY.
SELECT * FROM ZCI_11_D_ROOT UP TO lv_max_rows ROWS INTO CORRESPONDING F
IELDS OF TABLE lt_result_db ORDER BY (lt_order). "#EC CI_DYNTAB "#EC CI_DYNW
HERE
es_query_info-count = sy-dbcnt.
LOOP AT lt_result_db ASSIGNING <ls_result_db>.
MOVE-CORRESPONDING <ls_result_db> TO ls_result.
ls_result-key = <ls_result_db>-db_key.
INSERT ls_result INTO TABLE lt_result.
ls_key-key = <ls_result_db>-db_key.
INSERT ls_key INTO TABLE et_key.
ENDLOOP.
CATCH cx_sy_sql_error INTO lx_root.
ASSERT ID /bobf/dac CONDITION 0 = 1. RAISE EXCEPTION TYPE /bobf/cx_dac
EXPORTING previous = lx_root mv_node = is_ctx-node_key.
ENDTRY.
ENDIF.
* fill export parameters
IF is_query_options-paging_options-
paging_active = abap_true AND is_query_options-paging_options-
start_row IS NOT INITIAL.
IF is_query_options-paging_options-start_row > 1.
DELETE lt_result TO is_query_options-paging_options-start_row - 1.
ENDIF.
IF is_query_options-maximum_rows > 0.
lv_index = is_query_options-
maximum_rows + 1. DELETE et_key FROM lv_index.
ENDIF.
ENDIF.
et_data = lt_result.

6. Goto Extras ->Generate Repository Object -> Generate Constant Interface


Exercise 2: Query Invoice Instances
Create report ZCI_11_QUERY_INVOICE_INSTANCES. It shall print the IDs of all existing invoice
instances.
report zci_11_query_invoice_instances.

" get the service manager of the Invoice BO


data : lo_customer_invoice type ref to /bobf/if_tra_service_manager,
lt_selection_parameters type /bobf/t_frw_query_selparam,
ls_selection_parameters like line of lt_selection_parameters .
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = zif_ci_11_customer_invoice_c=>sc_bo_key ).
" query all existing invoices
data ls_root_data type zci_11_s_root.
data lt_root_data type zci_11_t_root.
lo_customer_invoice->query(
exporting
iv_query_key = zif_ci_11_customer_invoice_c=>sc_query-root-select_all
iv_fill_data = abap_true
importing
et_data = lt_root_data ).
" print all invoices ids
loop at lt_root_data into ls_root_data.
write / ls_root_data-invoice_id.
endloop.

" query SELECT_BY_ELEMENT invoices


clear : lt_root_data , ls_root_data.
ls_selection_parameters-attribute_name = 'INVOICE_ID'.
ls_selection_parameters-sign = 'I'.
ls_selection_parameters-option = 'EQ'.
ls_selection_parameters-low = '123'.
append ls_selection_parameters to lt_selection_parameters.
lo_customer_invoice->query(
exporting
iv_query_key = zif_ci_11_customer_invoice_c=>sc_query-root-
select_by_element " Query
it_selection_parameters = lt_selection_parameters " Query Selection Pa
rameters
importing
et_data = lt_root_data

).

loop at lt_root_data into ls_root_data.


write / ls_root_data-invoice_id.
endloop.
Exercise 3: Retrieve Invoice Items by Association
Create report ZCI_11_RETRIEVE_ITEMS. It shall calculate the sum of all item amounts of all invoices.

REPORT ZCI_11_RETRIEVE_ITEMS.

" get the service manager of the Invoice BO


DATA lo_customer_invoice TYPE REF TO /bobf/if_tra_service_manager.
data lt_root_data type zci_11_t_root.
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = zif_ci_11_customer_invoice_c=>sc_bo_key ).
" query all existing invoices
DATA lt_root_key TYPE /bobf/t_frw_key.
lo_customer_invoice->query(
EXPORTING
iv_query_key = zif_ci_11_customer_invoice_c=>sc_query-root-select_all
IMPORTING
et_data = lt_root_data
et_key = lt_root_key ).
" get all items
DATA ls_invoice_item TYPE zci_11_s_item.
DATA lt_invoice_item TYPE zci_11_t_item.
lo_customer_invoice->retrieve_by_association(
EXPORTING
iv_node_key = zif_ci_11_customer_invoice_c=>sc_node-root
it_key = lt_root_key
iv_association = zif_ci_11_customer_invoice_c=>sc_association-root-item
iv_fill_data = abap_true
IMPORTING
et_data = lt_invoice_item ).
" calculate all items
DATA lv_sum TYPE int4.
LOOP AT lt_invoice_item INTO ls_invoice_item.
lv_sum = lv_sum + ls_invoice_item-amount.
ENDLOOP.
WRITE lv_sum.
Creation of Action
We Need to create a Action if Incvoice is paid satus should be changed to Paid

1. Add an action on the root node to your business object that sets an Invoice Paid
status. You can name your action INVOICE_PAID.
2. Provide Class Interface name as ZCL_CI_11_A_INVOICE_PAID.

3. Implement the Method /BOBF/IF_FRW_ACTION~EXECUTE of the class Using Forward


Navigation and write the below code .
4.
data : lt_root TYPE zci_11_t_root,
lr_root TYPE ref TO zci_11_s_root.

IO_READ->RETRIEVE(
exporting
IV_NODE = ZIF_CI_11_CUSTOMER_INVOICE_C=>SC_NODE-
ROOT " Node Name
IT_KEY = it_key " Key Table
importing
ET_DATA = lt_root " Data Return Structure
).

LOOP at lt_root REFERENCE INTO lr_root.


lr_root->PAYMENT_STATUS = '02'.
io_modify->UPDATE(
exporting
IV_NODE = ZIF_CI_11_CUSTOMER_INVOICE_C=>sc_node-
root " Node
IV_KEY = lr_root->key " Key
IS_DATA = lr_root " Data
).
ENDLOOP.
5. Test Action Open Instance of INVOICE and Set action to INVOICE PAID.
Creation of Determination
Determine the total amount based on quantity and cost entered.

1. Expand ITEM node and create Determination Specify the Class Name as
ZCL_CI_11_D_ITEM_CALC_AMOUNT.
2. Implement the Method /BOBF/IF_FRW_DETERMINATION~EXECUTE of the class using forward
Navigation and write the Below Code.
data : lt_item type ZCI_11_T_ITEM,
LR_ITEM TYPE REF TO ZCI_11_S_ITEM.

IO_READ->RETRIEVE(
exporting
IV_NODE = zif_ci_11_customer_invoice_c=>SC_NODE-
ITEM " Node Name
IT_KEY = it_key " Key Table
importing
ET_DATA = lt_item " Data Return Structure
).

LOOP AT lt_item REFERENCE INTO lr_item.


lr_item->AMOUNT = lr_item->PRICE * lr_item->QUANTITY.
io_modify->UPDATE(
exporting
IV_NODE = zif_ci_11_customer_invoice_c=>SC_NODE-
ITEM " Node Name
IV_KEY = lr_item->key " Key
IS_DATA = lr_item " Data
* IT_CHANGED_FIELDS = " List of Names (e.g. Fieldnames)
).

ENDLOOP.

3. Test Determination .GO to Test ui (F8).


Creation of Validation
1. Open Structure ZCI_11_S_ROOT_D and add the few fields.

2. Create the required message in SE91.


3. Create required Message class.

4. Provide Message Text and Message class in TEXT tab.


5. Create Action Validation for ROOT node.

6. Provide Validation Name as CHECK_BILL_TO_PARTY and Class name as


ZCL_CI_11_V_BILLTO_PARTY.
7. Implement the Method /BOBF/IF_FRW_VALIDATION~EXECUTE using forward navigation and
write the below code.

data : lt_root TYPE zci_11_t_root,


lr_root TYPE REF TO zci_11_s_root,
ls_key TYPE /bobf/s_frw_key,
lo_messsage TYPE REF TO ZCM_CI_11_MESSAGE,
ls_location TYPE /bobf/s_frw_location.

CLEAR : eo_message, et_failed_key.


" Retrieve the root node data
io_read->RETRIEVE(
exporting
IV_NODE = ZIF_CI_11_CUSTOMER_INVOICE_C=>sc_node-
root " Node Name
IT_KEY = it_key " Key Table
importing
ET_DATA = lt_root " Data Return Structure
).
LOOP at lt_root REFERENCE INTO lr_root.
" Check for each node whether all bill-to-party are field
IF lr_root->party_name is INITIAL
or lr_root->party_street is INITIAL
or lr_root->PARTY_ZIP_CODE is INITIAL
or lr_root->PARTY_CITY is INITIAL .
" if not add the key to failed keys
ls_key-key = lr_root->key.
APPEND ls_key to et_failed_key.

" Create a corresponding cm-message


ls_location-bo_key = is_ctx-bo_key.
ls_location-node_key = is_ctx-node_key.
ls_location-key = lr_root->key.

CREATE OBJECT LO_MESSSAGE


EXPORTING
TEXTID = ZCM_CI_11_MESSAGE=>INCOMPLETE_BILL_TO_PARTY
SEVERITY = ZCM_CI_11_MESSAGE=>CO_SEVERITY_ERROR
SYMPTOM = /BOBF/IF_FRW_MESSAGE_SYMPTOMS=>CO_BO_INCONSISTENCY
LIFETIME = /bobf/if_frw_c=>SC_LIFETIME_SET_BY_BOPF
MS_ORIGIN_LOCATION = ls_location.
.
if EO_MESSAGE is NOT BOUND.
EO_MESSAGE = /BOBF/CL_FRW_FACTORY=>GET_MESSAGE( ).
endif.
" add the cm_messgae to the message handler
eo_message-
>ADD_CM( exporting IO_MESSAGE = LO_MESSSAGE ). " BOPF Message Class

ENDIF.
ENDLOOP.
8. Test Action validation. Goto test UI and Execute action INVOICE Issued.

Create Consistency Validation


Create a consistency validation which checks whether the invoice instance is consistent. In our case, the
invoice instance is consistent whenever the price currency of the items is EUR or USD.

1. Edit the Message class and add new Message.


2. Edit the class ZCM_CI_11_MESSAGE is SE24.

3. Create a consistency validation with the name CHECK_ITEM_CURRENCY_CODE as a consistency


validation assigned to the ITEM node.
4. Specify Validation name as CHECK_ITEM_CURRENCY_CODE and class name as
ZCL_CI_11_V_CHCK_ITM_CURRENCY

.
9. Implement the Method /BOBF/IF_FRW_VALIDATION~EXECUTE using forward navigation and
write the below code.
10.
data : lt_root TYPE zci_11_t_item,
ls_key TYPE /bobf/s_frw_key,
lo_messsage TYPE REF TO ZCM_CI_11_MESSAGE,
ls_location TYPE /bobf/s_frw_location.

FIELD-SYMBOLS : <ls_item> TYPE zci_11_S_item.


CLEAR : eo_message, et_failed_key.
" Retrieve the root node data
io_read->RETRIEVE(
exporting
IV_NODE = ZIF_CI_11_CUSTOMER_INVOICE_C=>sc_node-
item " Node Name
IT_KEY = it_key " Key Table
importing
ET_DATA = lt_root " Data Return Structure
).
LOOP at lt_root ASSIGNING <ls_item>.
" Check for each node whether all bill-to-party are field
if <ls_item>-currency ne 'EUR'
OR <LS_ITEM>-CURRENCY NE 'USD'.
" if not add the key to failed keys
ls_key-key = <LS_ITEM>-key.
APPEND ls_key to et_failed_key.

" Create a corresponding cm-message


ls_location-bo_key = is_ctx-bo_key.
ls_location-node_key = is_ctx-node_key.
ls_location-key = <LS_ITEM>-key.

CREATE OBJECT LO_MESSSAGE


EXPORTING
TEXTID = ZCM_CI_11_MESSAGE=>WRONG_CURRENCY_CODE
SEVERITY = ZCM_CI_11_MESSAGE=>CO_SEVERITY_ERROR
SYMPTOM = /BOBF/IF_FRW_MESSAGE_SYMPTOMS=>CO_BO_INCONSISTENC
Y
LIFETIME = /bobf/if_frw_c=>SC_LIFETIME_SET_BY_BOPF
MS_ORIGIN_LOCATION = ls_location.
.
if EO_MESSAGE is NOT BOUND.
EO_MESSAGE = /BOBF/CL_FRW_FACTORY=>GET_MESSAGE( ).
endif.
" add the cm_messgae to the message handler
eo_message-
>ADD_CM( exporting IO_MESSAGE = LO_MESSSAGE ). " BOPF Message Class

ENDIF.
ENDLOOP.
11. Goto Test UI and create and save data for ITEM
Creation of Alternative Keys.
1. Create Alternative Key under ROOT node.
2. Goto EXTRAS->Propose Repository Names.

3. Generate The Dictionary Object using Generate Repository.


4. Add the Index in ROOT table ZCI_11_D_ROOT.
5. Create a Action Validation for CHECK_UNIQUE_ALTKEY specify the class as
/BOBF/CL_LIB_V_ALT_KEY

Save and Regenerate the constant interface


Exercise 4: Convert Invoice ID

1. Create Programe ZCI_11_CONVERT_INVOICE_ID copy the below code and Execute the
Report.
REPORT ZCI_11_CONVERT_INVOICE_ID.

" get the service manager of the Invoice BO


DATA lo_customer_invoice TYPE REF TO /bobf/if_tra_service_manager.
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = zif_ci_11_customer_invoice_c=>sc_bo_key ).
" use alternative key conversion to get technical key
DATA lv_alternative_key TYPE int4.
DATA lt_alternative_key TYPE ZCI_11_T_K_INVOICE_ID.
DATA lt_root_key TYPE /bobf/t_frw_key.
lv_alternative_key = '123'.
APPEND lv_alternative_key TO lt_alternative_key.
lo_customer_invoice->convert_altern_key(
EXPORTING
iv_node_key = zif_ci_11_customer_invoice_c=>sc_node-root
iv_altkey_key = zif_ci_11_customer_invoice_c=>sc_alternative_key-root-
invoice_id
it_key = lt_alternative_key
IMPORTING
et_key = lt_root_key ).
" retrieve the instance data
DATA ls_root_data TYPE zci_11_s_root.
DATA lt_root_data TYPE zci_11_t_root.
lo_customer_invoice->retrieve(
EXPORTING
iv_node_key = zif_ci_11_customer_invoice_c=>sc_node-root
it_key = lt_root_key " Key Table
IMPORTING
et_data = lt_root_data ).
" print the payment_status
LOOP AT lt_root_data INTO ls_root_data.
WRITE: / ls_root_data-invoice_id, ls_root_data-payment_status.
ENDLOOP.
Exercise 5: Update All Invoice Instances.
Create report ZCI_11_UPDATE_ALL_INVOICES. It shall update thePAYMENT_STATUS of all existing
invoices to 02. Finally save the transaction.

REPORT ZCI_11_UPDATE_ALL_INVOICES.

" get the service manager of the Invoice BO


DATA lo_customer_invoice TYPE REF TO /bobf/if_tra_service_manager.
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = zif_ci_11_customer_invoice_c=>sc_bo_key ).
" query all existing invoices
DATA ls_root_data TYPE zci_11_s_root.
DATA lt_root_data TYPE zci_11_t_root.
lo_customer_invoice->query(
EXPORTING
iv_query_key = zif_ci_11_customer_invoice_c=>sc_query-root-select_all
iv_fill_data = abap_true
IMPORTING
et_data = lt_root_data ).
" update all invoices
DATA ls_modification TYPE /bobf/s_frw_modification.
DATA lt_modification TYPE /bobf/t_frw_modification.
DATA lr_root_data TYPE REF TO zci_11_s_root.
LOOP AT lt_root_data REFERENCE INTO lr_root_data.
lr_root_data->payment_status = '02'.
ls_modification-node = zif_ci_11_customer_invoice_c=>sc_node-root.
ls_modification-key = lr_root_data->key.
ls_modification-change_mode = /bobf/if_frw_c=>sc_modify_update.
ls_modification-data = lr_root_data.
APPEND ls_modification TO lt_modification.
ENDLOOP.
" execute modification
lo_customer_invoice->modify( it_modification = lt_modification ).
" save the transaction
DATA lo_transaction_manager TYPE REF TO /bobf/if_tra_transaction_mgr.
lo_transaction_manager = /bobf/cl_tra_trans_mgr_factory=>get_transaction_mana
ger( ).
lo_transaction_manager->save( ).
Exercise 7: Delete All Invoices
Create batch report ZCI_11_DELETE_ALL_INVOICES. It shall delete all existing invoices. Finally, save the
transaction.
DATA: lo_customer_invoice TYPE REF TO /bobf/if_tra_service_manager,
lt_root TYPE ZCI_11_T_Q_SELECT_ALL.
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = zif_ci_11_customer_invoice_c=>sc_bo_key ).
" query all existing invoices
DATA ls_root_key TYPE /bobf/s_frw_key.
DATA lt_root_key TYPE /bobf/t_frw_key.
lo_customer_invoice->query(
EXPORTING
iv_query_key = zif_ci_11_customer_invoice_c=>sc_query-root-select_all
IMPORTING
et_key = lt_root_key
et_data = lt_root ).
" delete all invoices
DATA ls_modification TYPE /bobf/s_frw_modification.
DATA lt_modification TYPE /bobf/t_frw_modification.
LOOP AT lt_root_key INTO ls_root_key.
ls_modification-node = zif_ci_11_customer_invoice_c=>sc_node-root.
ls_modification-key = ls_root_key-key.
ls_modification-change_mode = /bobf/if_frw_c=>sc_modify_delete.
APPEND ls_modification TO lt_modification.
ENDLOOP.
" execute modification
lo_customer_invoice->modify( it_modification = lt_modification ).
" save the transaction
DATA lo_transaction_manager TYPE REF TO /bobf/if_tra_transaction_mgr.
lo_transaction_manager = /bobf/cl_tra_trans_mgr_factory=>get_transaction_mana
ger( ).
lo_transaction_manager->save( ).
Exercise 8: Check Invoice Consistency
Create report ZCI_11_CHECK_INVOICE_CONSIST. It shall check the consistency of all Invoices.
REPORT ZCI_11_CHECK_INVOICE_CONSIST.

" get the service manager of the Invoice BO


DATA: lo_customer_invoice TYPE REF TO /bobf/if_tra_service_manager,
lt_root type ZCI_11_T_Q_SELECT_ALL.
lo_customer_invoice = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_
bo_key = zif_ci_11_customer_invoice_c=>sc_bo_key ).
" query all existing invoices
DATA lt_root_key TYPE /bobf/t_frw_key.
lo_customer_invoice->query(
EXPORTING
iv_query_key = zif_ci_11_customer_invoice_c=>sc_query-root-select_all
IMPORTING
et_key = lt_root_key
et_data = lt_root ).
" execute consistency validations triggering on check
DATA lo_message TYPE REF TO /bobf/if_frw_message.
lo_customer_invoice->check_consistency(
EXPORTING
iv_node_key = zif_ci_11_customer_invoice_c=>sc_node-root
it_key = lt_root_key
iv_check_scope = /bobf/if_frw_c=>sc_scope_substructure
IMPORTING
eo_message = lo_message ).
" get messages
DATA ls_message TYPE /bobf/s_frw_message_k.
DATA lt_message TYPE /bobf/t_frw_message_k.
lo_message->get_messages( IMPORTING et_message = lt_message ).
LOOP AT lt_message INTO ls_message.
" ...
ENDLOOP.
Advance Topics
Properties
Static Properties
1. Some node attributes must never be set directly from a user interface and should
therefore be read-only, for example the status values.

Switch to change mode, double-click on ROOT beneath Node Elements -> ROOT -> Node Categories, and
choose the tab Attribute Properties. Mark the Read-Only flags of the status fields.

Go to Test UI The status fields are can no longer be edited on the user interface.
Dynamic Properties
Ensure that, if an invoice has been issued, the invoice ID is always switched to read-only to avoid any
changes being made to the ID later.

To do this, create a property determination that checks the status (ISSUANCE_STATUS). Specify class
name as ZCL_CI_11_D_ROOT_PROPERTIES.
Implement the Method /BOBF/IF_FRW_DETERMINATION~EXECUTE write the below code.

data : lo_set_property type ref to /bobf/cl_lib_h_set_property,


lt_root type zci_11_t_root.
field-symbols <ls_root> type zci_11_s_root.

clear :eo_message, et_failed_key.

** Retrieve root node data for given keys


io_read->retrieve(
exporting
iv_node = zif_ci_11_customer_invoice_c=>sc_node-
root " Node Name
it_key = it_key " Key Table
importing
et_data = lt_root " Node Category Assignment
).

" Create service object for dynamic properties


create object lo_set_property
exporting
is_context = is_ctx " Context Information for Determinations
io_modify = io_modify. " Interface to Change Data

loop at lt_root assigning <ls_root>.


if <ls_root>-issuance_status eq 'X'.
" Invoice has been issued ensure that invoice_id is read only
lo_set_property->set_attribute_read_only(
exporting
iv_attribute_name = zif_ci_11_customer_invoice_c=>sc_node_attribute-
root-invoice_id " Name of the attribute for which the property is to be set
iv_key = <ls_root>-
key " Key of the instance for which the property is to be set
iv_value = abap_true " New value of this property (true/
false)
).
endif.
endloop.

Goto Test UI and Execute Action Invoice Issued.


Special Associations
1. Add a new field ITEM_CATEGORY (of type CHAR 1) to your item structure
ZCI_11_S_ITEM_D.

2. Create a new interface ZIF_CI_11_CONSTANTS_C where you define the two constant
values GC_NORMAL_ITEM = space and GC_SERVICE_ITEM = S for the new field
ITEM_CATEGORY.

3. Create a Association TO_SERVICE_NODE under the ROOT node .


Goto Test UI Create one item as Category S.
Now Retrieve association TO_SERVICE_NODE .

Result will come only for ITEM_CATEGORY as S


Advance Feature
Late Numbering

If an ID or number of a document is created using a number range and if gaps are not allowed within
the numbers (e.g. for legal purposes), the number should be used only if the transaction is successfully
saved.

1. Add Field GAPLESS_ID (type NUMC_5) in ROOT structure.


2. Use transaction SNRO to create a new number range object ZCI_11_ID.

Maintain Interval.
3. Create a determination for ROOT named FILL_TMP_GAPLESS_ID specify class name as
ZCL_CI_11_D_ROOT_FILL_TMP_ID.
Save and regenerate the constant interface.

Goto Generate Class ZCL_CI_11_D_ROOT_FILL_TMP_ID and add two static attributes to your classes
GV_TMP_GAPLESS_ID (type INT2, initial value = 1) and GT_ADJUSTED_NUMBER (type
/BOBF/T_FRW_ADJUSTED_NUMBERS).
4. Implement the Method /BOBF/IF_FRW_DETERMINATION~EXECUTE
data : lt_root type zci_11_t_root,
lr_root TYPE REF TO zci_11_s_root,
lv_tmp_gapless_id(2) TYPE c,
ls_adjusted_number TYPE /bobf/s_frw_adjusted_numbers.

clear :eo_message, et_failed_key.

** Retrieve root node data for given keys


io_read->retrieve(
exporting
iv_node = is_ctx-node_key " Node Name
it_key = it_key " Key Table
importing
et_data = lt_root " Node Category Assignment
).

LOOP at lt_root REFERENCE INTO lr_root.


lv_tmp_gapless_id = gv_tmp_gapless_id.
CONCATENATE 'tmp' lv_tmp_gapless_id into lr_root->gapless_id.
gv_tmp_gapless_id = gv_tmp_gapless_id + 1.
io_modify->update(
exporting
iv_node = is_ctx-node_key
iv_key = lr_root->key " Key
is_data = lr_root " Data
).
ENDLOOP.
" buffer mapping between node key and temp ID
ls_adjusted_number-bo_name = zif_ci_11_customer_invoice_c=>sc_bo_name.
ls_adjusted_number-bo_node_name = zif_ci_11_customer_invoice_c=>sc_node-
root.
ls_adjusted_number-node_id = lr_root->key.
ls_adjusted_number-
attribute_name = zif_ci_11_customer_invoice_c=>sc_node_attribute-root-
gapless_id.
ls_adjusted_number-old_attribute_value = lr_root->gapless_id.
APPEND ls_adjusted_number to gt_adjusted_number.

_
Create Determination FILL_FINAL_GAPLESS_ID specify the class name as
ZCI_CL_11_D_ROOT_FILL_GAPL_ID.
Save the BO and regenerate the constants interface.
5. Generate the class ZCL_CI_11_D_ROOT_FILL_GAPL_ID and Implement the method
/BOBF/IF_FRW_DETERMINATION~EXECUTE

data : lt_root type zci_11_t_root,


lr_root type ref to zci_11_s_root,
lv_node_id type /bobf/conf_key,
lv_number type int4,
lv_tmp_gapless_id_string type string .

field-
symbols : <ls_adjusted_number> type /bobf/s_frw_adjusted_numbers.
clear :eo_message, et_failed_key.
sort zcl_ci_11_d_root_fill_tmp_id=>gt_adjusted_number by old_attribute_va
lue.
** Retrieve root node data for given keys
io_read->retrieve(
exporting
iv_node = is_ctx-node_key " Node Name
it_key = it_key " Key Table
importing
et_data = lt_root " Node Category Assignment
).
sort lt_root by gapless_id.

loop at lt_root reference into lr_root.


" Replace the Tem GAPLESS_ID with a final value for each nod.
" Check if this item has temo GAPLESS id
check lr_root->gapless_id ca 'tmp'.
" is this temp GAPLESS id is buffered ? if not , Programming error -
> dump

lv_tmp_gapless_id_string = lr_root->gapless_id.
read table zcl_ci_11_d_root_fill_tmp_id=>gt_adjusted_number assigning <
ls_adjusted_number>
with key old_attribute_value = lv_tmp_gapless_id_string binary search .
assert sy-subrc is initial.
" do the node by the input and the buffered key coincide?
" if not , programming error

lv_node_id = <ls_adjusted_number>-node_id.
assert lv_node_id eq lr_root->key.

" retrieve next no. form get number


call function 'NUMBER_GET_NEXT'
exporting
nr_range_nr = '01'
object = 'ZCI_11_ID'
importing
number = lv_number
exceptions
interval_not_found = 1
number_range_not_intern = 2
object_not_found = 3
quantity_is_0 = 4
quantity_is_not_1 = 5
interval_overflow = 6
buffer_overflow = 7
others = 8.
if sy-subrc <> 0.
* Implement suitable error handling here
endif.

assert sy-subrc is initial.


" FILL final GAPLESS ID into root data and into buffer table
lr_root->gapless_id = lv_number.
<ls_adjusted_number>-new_attribute_value = lr_root->gapless_id.
io_modify->update(
exporting
iv_node = is_ctx-node_key " Node
iv_key = lr_root->key " Key
is_data = lr_root " Data
).

endloop.
6. goto Test UI and create a entry.