Enterprise Resource Planning Blogs by SAP
Get insights and updates about cloud ERP and RISE with SAP, SAP S/4HANA and SAP S/4HANA Cloud, and more enterprise management capabilities with SAP blog posts.
cancel
Showing results for 
Search instead for 
Did you mean: 
varunvenkat
Product and Topic Expert
Product and Topic Expert
In Part 3 of the Enhancing the Standard Series, I’ll be showing you how to facilitate a “process integration” between a sales quotation and a service contract in S/4HANA Cloud. As these are two unrelated documents from different Lines-of-Business, there is no document flow between these documents in the standard process. By using a user-defined “dummy rejection reason” in the sales quotation, and a Custom Business Object (CBO) to convert these items into service contracts, a “process integration” can be established between a sales document and a service document.

Business background


The business requirement for having this integration is as follows. The company offers sales products and service contract products in a single quotation to the customer. As the CPQ system is not used, there is no possibility to issue a solution quote and convert this into a subsequent solution order. Due to this, the company’s process is to use a sales quotation as the starting document, where the service contract products (with a different item category group) are also included.

The next step is to define a dummy rejection reason to signify if the customer has accepted the quote for the service contract products. All other sales items can be automatically converted to a sales order, however the service contract items need to be “rejected”, so that they can be separately created as a service contract. If the customer declines the service contract items, the real rejection reason will be set, and if the customer accepts the items, the dummy rejection reason will be set.

In the final step, a CBO will be created that fetches all sales quotation items, where the dummy rejection reason defined in the previous step was set. The CBO will also act as a checklist, where the customer service manager can update the status of the CBO item, once the service contract for the rejected sales quotation item has been created. Optionally, the CBO could also be enhanced so that the customer service manager could automatically create the service contract header from within the CBO, by using the sold-to-party from the sales quotation. However, only the contract header can be created due to the different item category groups between the service contract product IDs in the sales quotation and the “real” service contract product IDs (this won’t be covered in the scope of this blog post).

The overall concept therefore offers a streamlined process integration, as there is a central handover between the process steps carried out by the sales representative and the customer service manager. Once the sales rep uses the dummy rejection reason for a particular customer, the customer service manager can consume this new item in the CBO and accordingly create a new service contract for the customer.

Process in the system


Having set the scene, let’s look at the processes steps for this process integration in the system.

As mentioned, the first step is to create a dummy rejection reason that will be used to convey that they customer has actually accepted the service contract product in the sales quotation

  • In customizing (SSCUI 102494), create a new rejection reason (in my example, ‘89’)


  • Create the CBO in the app “Custom Business Object”. Use the following parameters:






 

Add the following code to the ‘Fetch Quotations’ logic of the CBO:
* Action FetchQuotations for Node ID SALES_QUOTE_CONVERSION
*
* Importing Parameter : association (Navigation to Parent/Child/Associated Node Instances)
* write (API for creating and updating Custom Business Object Node Instances)
* Changing Parameter : SALES_QUOTE_CONVERSION (Current Node Data)
* Exporting Parameter : message (Message with Severity S(uccess), W(arning), E(rror))

"define local variables

data: lv_sc_key_counter type int8.
data: lv_table_counter type int8.

data: lv_rejection_reason_sc type int8.
lv_rejection_reason_sc = 89.

DATA lv_root_entity_key TYPE yy1_kr_sales_quote_conversion.
lv_root_entity_key = SALES_QUOTE_CONVERSION-conversiontype.

* Get an instance of the root entity of the CBO
DATA(lo_root) = write->get_root(
business_object_id = 'YY1_SALES_QUOTE_CONVERSION'
key = lv_root_entity_key
).

"data: lv_conversion_type type string.
"lv_conversion_type = |{ quote_dashboard-conversiontype ALPHA = IN }|.

*-------------------------------------------------------------------------------------------------------------------------------------------*

"Logic to create new Follow-up Service Contract Sales Quotations

*Select required columns from the released I_SalesQuotationItem CDS View
SELECT SalesQuotation, SalesQuotationItem, SalesDocumentRjcnReason
FROM I_SalesQuotationItem
INTO TABLE @data(sq_table_sc)
where SalesDocumentRjcnReason = @lv_rejection_reason_sc.

"Get existing CBO entries to check for duplicates before creating child nodes of SQ Sales Order
SELECT SalesQuotation, SQItem
FROM yy1_cbo_sq_89
INTO TABLE @data(sq_cbo_table_sc)
where RejectionReason = @lv_rejection_reason_sc.

LOOP AT sq_table_sc INTO DATA(ls_sq_sc_row).

DATA lv_existing_sq_sc_key TYPE string.
DATA lv_new_sq_sc_key TYPE string.
"Reset counter to 0
lv_sc_key_counter = 0.
"Check if CBO internal table is empty. If yes, loop won't have an index, due to which no child nodes can be created
IF sq_cbo_table_sc IS INITIAL.
Data(ls_first_sq_sc_entry) = VALUE yy1_service_contract_sales_quo(
salesquotation = ls_sq_sc_row-salesquotation
rejectionreason = ls_sq_sc_row-salesdocumentrjcnreason
sqitem = ls_sq_sc_row-salesquotationitem
).
lo_root->create_child(
EXPORTING
Node_id = 'Service_Contract'
Data = ls_first_sq_sc_entry
).
CONTINUE.
ENDIF.

LOOP AT sq_cbo_table_sc INTO DATA(sq_cbo_sc_row).
CONCATENATE sq_cbo_sc_row-salesquotation sq_cbo_sc_row-sqitem INTO lv_existing_sq_sc_key.
CONCATENATE ls_sq_sc_row-salesquotation ls_sq_sc_row-salesquotationitem INTO lv_new_sq_sc_key.
"If primary key already exists, skip the loop and don'r create new CBO entry
IF lv_new_sq_sc_key = lv_existing_sq_sc_key.
"As soon as even the first index loop through the current CBO entries
"matches a potential new entry, break out of the loop, because the primary key already exists
lv_sc_key_counter = lv_sc_key_counter + 1.
EXIT.
ELSE.
CONTINUE.
ENDIF.
ENDLOOP.
"After looping through entire CBO table, and if no matches are found, only then create a new SQ (Sales Order) child node
IF lv_sc_key_counter eq 0.
Data(ls_new_sq_sc_entry) = VALUE yy1_service_contract_sales_quo(
salesquotation = ls_sq_sc_row-salesquotation
rejectionreason = ls_sq_sc_row-salesdocumentrjcnreason
sqitem = ls_sq_sc_row-salesquotationitem
).

SELECT Single Customer
FROM I_SalesQuotationPartner
INTO @data(sq_sc_item_customer)
where salesquotation = @ls_sq_sc_row-salesquotation.
ls_new_sq_sc_entry-customer = sq_sc_item_customer.
lo_root->create_child(
EXPORTING
Node_id = 'Service_Contract'
Data = ls_new_sq_sc_entry
).
ENDIF.

ENDLOOP.

*-------------------------------------------------------------------------------------------------------------------------------------------*

message = VALUE #(
severity = co_severity-success
text = 'Action FetchQuotations executed'
).

 

The CBO created essentially reads all sales quotation items with the rejection reason ‘89’ from the respective CDS View and loads these entries into the CBO, so that the customer service manager can review them and create service contracts.

One important additional step to be done is to create a Custom CDS View for the CBO that has just been created. This is used to perform a duplicate check while fetching sales quotations into the CBO, so that the same sales quotation item doesn’t appear multiple times.



 

  • Now that all setup steps have been completed, it’s time to see the overall process integration play out. The sales representative would create a test sales quotation, where the service contract product (with item category group SERV) is offered to the customer. For this sales quotation item, the dummy rejection reason defined above will be set to signify that the customer has accepted this quotation item.


  • The customer service manager can now go to the UI of the CBO. In this UI, a root node needs to be created initially, as all sales quotation items will be created as child nodes of this root node. Inside the root node, execute the action “Fetch Quotations”.



  • With this step, the sales quotation item that is pending action to be taken by the customer service manager is fetched. The customer service manager can now go through these items and use the CBO as a sort of “handover checklist” from the sales rep, to track which sales quotation items have been converted into service contracts, and which items are still pending.

  • Once a new service contract has been created, the customer service manager can edit the CBO entry, set the checkbox to completed, and maintain the created service contract ID as a reference.



That concludes part 3 of the enhancing the standard series. Hope this provided an interesting approach on how such process integrations can be achieved between documents from different LoBs by using extensibility tools such as CBOs that are available in S/4HANA Cloud. In case you haven’t checked out Part 1 and 2 of the series yet, you can find the overview of the topics covered so far here.