Adding determinations
In the previous part we were able to provide our app with basic functionalities. By now our app should be able to:
◈ Search for Sales Orders
◈ List Sales Orders
◈ Display Sales Order details
◈ Lock Sales Orders
◈ Delete Sales Orders
In this part of the blog series we’ll focus on creating and changing Sales Orders draft instances. We’ll do that by:
◈ Adding custom determinations
◈ To generate a temporary Sales Order number for new draft Sales Orders
◈ To generate a new item number when adding an item to a draft Sales Order
◈ To simulate a sales order
Because we’re working with a legacy key (and not using a GUID key field), we’ll need to add custom determinations to fill the legacy key fields and to simulate a sales order.
Generating a temporary Sales Order number and setting default header data
Open up the BOPF Business Object and go to the root node.
Once you are in the root node, open the determinations.
Add a new determination using the “New…” button.
Enter following details in the popup and click “Finish“. Afterwards activate the Business Object
Open up the new determination (using CTRL+Click) and activate it only for the Create event as shown below.
Open the newly generated class.
Add following logic to method /BOBF/IF_FRW_DETERMINATION~EXECUTE. This determination will provide the draft instance (only in create mode) with:
◈ A fixed temporary sales order number ($000000001)
◈ A fixed order type (OR => internal TA)
◈ Created by, created on, created at
◈ Initial values (based on user parameters) for sales organization, distribution channel and division
METHOD /bobf/if_frw_determination~execute.
DATA lt_data TYPE ztsdi_soheader.
* Read data with the given keys
io_read->retrieve(
EXPORTING
iv_node = is_ctx-node_key " uuid of node name
it_key = it_key " keys given to the determination
IMPORTING
eo_message = eo_message " pass message object
et_data = lt_data " itab with node data
et_failed_key = et_failed_key " pass failures
).
* Assign numbers to each newly created line and tell BOPF about the modification
LOOP AT lt_data REFERENCE INTO DATA(lr_data) WHERE vbeln IS INITIAL.
lr_data->vbeln = '$000000001'.
lr_data->auart = 'TA'.
lr_data->erdat = sy-datum.
lr_data->ernam = sy-uname.
lr_data->erzet = sy-uzeit.
GET PARAMETER ID 'VKO' FIELD lr_data->vkorg.
GET PARAMETER ID 'VTW' FIELD lr_data->vtweg.
GET PARAMETER ID 'SPA' FIELD lr_data->spart.
io_modify->update(
EXPORTING
iv_node = is_ctx-node_key " uuid of node
iv_key = lr_data->key " key of line
is_data = lr_data " ref to modified data
it_changed_fields = VALUE #( ( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-vbeln )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-auart )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-vkorg )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-vtweg )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-spart )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-erdat )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-ernam )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-erzet ) )
).
ENDLOOP.
ENDMETHOD.
Generating a Sales Order item number based on customizing
When creating a new Sales Order item a new item number needs to be generated. For this we’ll need to create a new determination on the item node of the BOPF Business Object. To do so, open the item node and switch to the determination view.
Add a new determination using the “New…” button.
Enter following details in the popup and click “Finish“. Afterwards activate the Business Object.
Open up the new determination (using CTRL+Click) and activate it only for the Create event as shown below.
Add following logic to method /BOBF/IF_FRW_DETERMINATION~EXECUTE of the newly generated class. This determination will provide the draft instance with logic to:
◈ Determine the highest item number in the draft instance
◈ Read the item interval from customizing
◈ Increment the item number with the item interval in customizing
METHOD /bobf/if_frw_determination~execute.
DATA: lt_header_data TYPE ztsdi_soheader,
lt_item_data TYPE ztsdi_soitem,
lt_header_key TYPE /bobf/t_frw_key.
* Read data with the given keys (item data)
io_read->retrieve(
EXPORTING
iv_node = is_ctx-node_key " uuid of node name
it_key = it_key " keys given to the determination
IMPORTING
eo_message = eo_message " pass message object
et_data = lt_item_data " itab with node data
et_failed_key = et_failed_key " pass failures
).
* Read root key to determine header data
READ TABLE lt_item_data INTO DATA(ls_item_data) INDEX 1.
lt_header_key = VALUE #( ( key = ls_item_data-root_key ) ).
* Read header data based on root key
io_read->retrieve(
EXPORTING
iv_node = zif_sd_i_soheader_c=>sc_node-zsd_i_soheader " uuid of node name
it_key = lt_header_key " keys given to the determination
IMPORTING
eo_message = eo_message " pass message object
et_data = lt_header_data " itab with node data
et_failed_key = et_failed_key " pass failures
).
* Read header data
READ TABLE lt_header_data INTO DATA(ls_header_data) INDEX 1.
* Get highest value of position number in draft table
SELECT MAX( posnr ) FROM zsd_soitem_d
INTO @DATA(lv_posnr)
WHERE parentdraftuuid = @ls_header_data-key.
"WHERE vbeln = @ls_header_data-vbeln.
* Get item interval from order type customizing
SELECT SINGLE incpo FROM tvak
INTO @DATA(lv_increment)
WHERE auart = @ls_header_data-auart.
* Assign numbers to each newly created line and tell BOPF about the modification
LOOP AT lt_item_data REFERENCE INTO DATA(lr_item_data) WHERE posnr IS INITIAL.
ADD lv_increment TO lv_posnr.
lr_item_data->vbeln = ls_header_data-vbeln.
lr_item_data->posnr = lv_posnr.
lr_item_data->erdat = sy-datum.
lr_item_data->ernam = sy-uname.
lr_item_data->erzet = sy-uzeit.
io_modify->update(
EXPORTING
iv_node = is_ctx-node_key " uuid of node
iv_key = lr_item_data->key " key of line
is_data = lr_item_data " ref to modified data
it_changed_fields = VALUE #( ( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-vbeln )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-posnr )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-erdat )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-ernam )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-erzet ) )
).
ENDLOOP.
ENDMETHOD.
Simulating a sales order
When changing a field (either on header or item level) we’ll need to recalculate the order value. For this we’ll create an additional determination that is triggered when changing both the header and item nodes of the business object.
Add a new determination on the root node (same steps as in the first part of this blog) and enter following details in the popup.
In the determination screen add the item node using the “New ” button.
Enable the determination for both nodes on update.
Add following logic to method /BOBF/IF_FRW_DETERMINATION~EXECUTE of the newly generated class. This determination will provide the draft instance with logic to:
◈ Simulate a sales order with the changes in the draft instance
◈ Pass errors in simulation to the Fiori App
◈ Recalculate the item and header price of the sales order
METHOD /bobf/if_frw_determination~execute.
DATA: lt_header_data TYPE ztsdi_soheader,
lt_item_data TYPE ztsdi_soitem.
DATA: ls_header TYPE bapisdhead,
lt_items_in TYPE TABLE OF bapiitemin,
lt_items_out TYPE TABLE OF bapiitemex,
lt_partners TYPE TABLE OF bapipartnr,
lt_messages TYPE bapiret2_t.
* Read header data with the given keys
io_read->retrieve(
EXPORTING
iv_node = is_ctx-node_key " uuid of node name
it_key = it_key " keys given to the determination
IMPORTING
eo_message = eo_message " pass message object
et_data = lt_header_data " itab with node data
et_failed_key = et_failed_key " pass failures
).
READ TABLE lt_header_data INTO DATA(ls_header_data) INDEX 1.
* Read item data with the given keys
io_read->retrieve_by_association(
EXPORTING
iv_node = is_ctx-node_key
it_key = it_key
iv_association = zif_sd_i_soheader_c=>sc_association-zsd_i_soheader-_items
iv_fill_data = abap_true
IMPORTING
eo_message = eo_message
et_data = lt_item_data
et_failed_key = et_failed_key
).
* Set sales order header data
ls_header = VALUE #( doc_type = ls_header_data-auart
sales_org = ls_header_data-vkorg
distr_chan = ls_header_data-vtweg
division = ls_header_data-spart
sales_off = ls_header_data-vkbur
sales_grp = ls_header_data-vkgrp
purch_no = ls_header_data-bstnk ).
* Set sales order partners
lt_partners = VALUE #( ( partn_role = 'AG' partn_numb = ls_header_data-kunnr )
( partn_role = 'WE' partn_numb = ls_header_data-kunwe ) ).
LOOP AT lt_item_data INTO DATA(ls_item_data).
APPEND VALUE #( itm_number = ls_item_data-posnr
material = ls_item_data-matnr
req_qty = ls_item_data-kwmeng * 1000
sales_unit = ls_item_data-vrkme
short_text = ls_item_data-arktx ) TO lt_items_in.
ENDLOOP.
* Simulate sales order
CALL FUNCTION 'BAPI_SALESORDER_SIMULATE'
EXPORTING
order_header_in = ls_header
* convert_parvw_auart = space
TABLES
order_items_in = lt_items_in
order_partners = lt_partners
order_items_out = lt_items_out
messagetable = lt_messages.
IF line_exists( lt_messages[ type = 'E' ] ).
* Create message object
eo_message = /bobf/cl_frw_factory=>get_message( ).
* Pass messages from BAPI to BOPF framework
LOOP AT lt_messages INTO DATA(ls_message).
eo_message->add_message(
EXPORTING
is_msg = VALUE #( msgty = ls_message-type
msgid = ls_message-id
msgno = ls_message-number
msgv1 = ls_message-message_v1
msgv2 = ls_message-message_v2
msgv3 = ls_message-message_v3
msgv4 = ls_message-message_v4 )
).
ENDLOOP.
ELSE.
CLEAR: ls_header_data-waerk,
ls_header_data-netwr.
* Set item data
LOOP AT lt_item_data REFERENCE INTO DATA(lr_item_data).
READ TABLE lt_items_out INTO DATA(ls_item_out) WITH KEY itm_number = lr_item_data->posnr.
IF sy-subrc = 0.
lr_item_data->matnr = ls_item_out-material.
lr_item_data->arktx = ls_item_out-short_text.
lr_item_data->kwmeng = ls_item_out-req_qty.
lr_item_data->vrkme = ls_item_out-sales_unit.
lr_item_data->netwr = ls_item_out-net_value / 100.
lr_item_data->waerk = ls_item_out-currency.
io_modify->update(
EXPORTING
iv_node = zif_sd_i_soheader_c=>sc_node-zsd_i_soitem " uuid of node
iv_key = lr_item_data->key " key of line
is_data = lr_item_data " ref to modified data
it_changed_fields = VALUE #( ( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-matnr )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-arktx )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-kwmeng )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-vrkme )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-netwr )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soitem-waerk ) )
).
ADD ls_item_out-net_value TO ls_header_data-netwr.
ls_header_data-waerk = ls_item_out-currency.
ENDIF.
ENDLOOP.
* Set header data
LOOP AT lt_header_data REFERENCE INTO DATA(lr_header_data).
lr_header_data->netwr = ls_header_data-netwr / 100.
lr_header_data->waerk = ls_header_data-waerk.
io_modify->update(
EXPORTING
iv_node = zif_sd_i_soheader_c=>sc_node-zsd_i_soheader " uuid of node
iv_key = lr_header_data->key " key of line
is_data = lr_header_data " ref to modified data
it_changed_fields = VALUE #( ( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-netwr )
( zif_sd_i_soheader_c=>sc_node_attribute-zsd_i_soheader-waerk ) )
).
ENDLOOP.
ENDIF.
ENDMETHOD.
Our business object is now ready to handle draft instances of Sales Orders. In the next part we’ll handle the conversion of the draft instance into a real Sales Order.
No comments:
Post a Comment