SAP Cloud for Customer is the new Customer-Centric Enterprise Cloud solution designed and released by SAP for the Customer Engagement and Relationship Management. This new solution enables you to align the business organizations and units around the Customer, with Marketing, Sales and Customer Service functionalities at the front line to the Customer.
In the new SDK Framework provided with SAP C4C (called SAP Cloud Application Studio) the main advantage is the model of Designing and Programming based on Business Objects. Every business document, or (as we say in the old SAP CRM taxonomy) business Transaction, can be seen as an instance of a specific class: the business object, with inside all the contained data and fields seen as a member properties, and with all the actions seen as class methods. The picture below shows the architecture of the Service Request Business Object:
The advantage of this programming model is that the designer is not just free to use the given actions programmatically in the code, but even to define and extend the BO with new fields, new referenced child BO and new actions.
In this article we focus on an implementation sample based on the following case: consider a Customer Service Scenario, where a lot of different Tickets are opened by the Customer Service team, department or Organizational Unit. For some particular Service Category it could be useful to define a specific subset of Mandatory field, and enable or disable some of the Tabs available in the Ticket UI screens, in a way that the Tickets have all the required information for being submitted and any rework on the Tickets could be avoided.
We are then interested in implementing the following base requirements:
The following articles will define the Solution built for achieving the two requirements.
Although in Premise/CRM implementations this task could have been easily achieved via Incompleteness Check Configuration, this task cannot be achieved via configuration in C4C. The Cloud solution offers a partial implementation of the Incompleteness Check called “Code List Restrictions”, but it’s a really limited functionality. As you can see from the picture below, for the Business Object Ticket, you can adjust some restriction just in few fields:
Then, the solution has been taken in account is to implement an extension on the standard Ticket Business Object.
At first we considered to act at Front-End/UI level, by modifying just the way the field “Incident Category” appears as mandatory or not in the New Ticket Quick View. But this logic didn’t work. The reason was that is not possible to act on the validation logic of the field “Service Category” (the framework won’t allow you to change that propriety, since the Extensibility framework is enabled).
The definitive solution adopted is based on the following steps:
· At the back-end/BO level: to add a custom logic on the Before-Save events for the Service Request Business Object;
· At the front-end/UI level: to add a custom rule on how the Incident Category field is displayed (as mandatory on not);
· (Optional) on the Business Configuration: define a table of Service Category codes which the Incident Category should be mandatory for.
The solution steps have been illustrated in details in the following sections.
With the same logic it is possible to bind and then control the behaviour of the UI Embedded Components for a more complex View (for instance the tabs of a WorkCenter), in order to achieve our goal.
In a new Solution, we define a new Business Object Extension, shown in the picture below:
We chose the name US01_TicketIncidentCategoryEnhancement.xbo. The base BO to select for Tickets is the ServiceRequest, as shown in the picture below:
The extension will be based on just an Indicator/Checkbox (read-only) that will be useful to track the need of a mandatory Incident Category field.
The code for the Extension is shown below:
import AP.CRM.Global;
import AP.Common.GDT;
[Extension] businessobject AP.CRM.Global:ServiceRequest raises MsgMandatoryCheck {
messageMsgMandatoryCheck text "Service Category &1 requires a mandatory value for Incident Category.":LANGUAGEINDEPENDENT_SHORT_Name;
node Item {
}
node ServiceReferenceObject {
}
[Label ("Verification Flag")] elementVerificationFlag:Indicator;
}
Since we need to act on the data validation before the save, the following Script Files will be implemented too:
· Event: BeforeSave;
· Validation: OnSave.
The following sections contain the code snippets taken from both files. In this section we mention that an easy way to find out where the information displayed in the fields are available in the BO, by using the UI Binding information.
At first, create an enhancement on the CreateNewTicket_QA screen, as shown in the picture below:
And then open the QA view in the UI designer. Open the “Designer” tab on the left and the “BO Browser/Data Model” on the right. If you click on the single field on the Designer tab, you can see the following matches between front-end and back-end:
→ | ||
→ |
We discovered then that the field values will be accessible in the BO model by the following attributes:
· Service Category: this.ServiceTerms.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID
· Incident Category: this.MainIncidentServiceIssueCategory.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID
After this discovery, the logic code is easy to write:
1. On save, if the Service Category has been populated with “AS” and the Incident Category is empty, then:
1.1. raise and display an error message;
1.2. Set the Verification Flag to true.
import ABSL;
this.flgCustomer= false;
this.flgIncidentCat= false;
this.flgProduct= false;
this.flgSerialId= false;
//var servIC = this.ServiceTerms.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID;
//var incdIC = this.MainIncidentServiceIssueCategory.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID;
var tktCustomer= "A";
var tktProduct= this.MainServiceReferenceObject.MaterialKey.ProductID;
var tktSerialID= this.MainServiceReferenceObject.IndividualProductSerialIDKey.SerialID;
var tktServiceCat= this.ServiceTerms.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID;
var tktIncidentCat= this.MainIncidentServiceIssueCategory.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID;
if (!tktServiceCat.IsInitial()) {
/*
var count = SERVICECATEGORYLIST.QueryByElements.Count();
var bcoServICList = SERVICECATEGORYLIST.QueryByElements.Execute();
var isPresentInConf = false;
*/
var bcoServICList = SERVCAT_MADATORYFIELDS.QueryByElements.Execute();
var isPresentInConf = false;
var bcoServiceCategory;
foreach(var bcoServICItemin bcoServICList) {
if(bcoServICItem.SERV_CAT.content == tktServiceCat.content) {
isPresentInConf= true;
bcoServiceCategory= bcoServICItem;
}
}
// if(servIC.content == "AS") isPresentInConf = true;
/*
if (isPresentInConf && incdIC.IsInitial()) {
raise MsgMandatoryCheck.Create("E", servIC.content);
this.VerificationFlag = true;
} else this.VerificationFlag = false;
*/
if (isPresentInConf) {
if(bcoServiceCategory.INCD_CAT == true&& tktIncidentCat.IsInitial()) {
raiseMsgMandatoryCheck.Create("E", tktServiceCat.content, "Incident Category");
this.flgIncidentCat = true;
}
/*
if (bcoServiceCategory.CUSTOMER == true && tktCustomer.IsInitial()) {
raise MsgMandatoryCheck.Create("E", tktServiceCat.content, "Customer");
this.flgCustomer = true;
}
*/
if(bcoServiceCategory.PRODUCT == true && tktProduct.IsInitial()) {
raiseMsgMandatoryCheck.Create("E", tktServiceCat.content, "Product");
this.flgProduct = true;
}
if(bcoServiceCategory.SERIAL_ID == true&& tktSerialID.IsInitial()) {
raiseMsgMandatoryCheck.Create("E", tktServiceCat.content, "Serial ID");
this.flgSerialId = true;
}
}
} else {
this.flgCustomer = false;
this.flgIncidentCat = false;
this.flgProduct = false;
this.flgSerialId = false;
}
Since the information of the validation is in the flag, the Validation result is just the negative of the flag itself:
import ABSL;
return !(this.flgCustomer||this.flgIncidentCat||this.flgProduct||this.flgSerialId);
Since we create an enhancement on the CreateNewTicket_QA screen, we now edit the behaviour of the fields in the UI. After opening the UI Designer, follow the following steps:
1. Open the “Extensibility Explorer” tab and select the second row (Section Group):
2. Select the operation “Add Extension Field to Section Group”. A pop-up will appear as shown below:
3. Add the Verification Flag in Display Only mode. Then, Save and Activate the screen;
4. Select the operation “Adjust Properties”, the three fields (Service Category, Incident Category, and Verification Flag) will have the following configuration in the pop-up window:
Where the Incident Category has been bound to the Verification Flag, as shown below:
5. Select the operation “Change SectionGroup”, and disable the Verification Flag from the screen (should be hidden), as shown below:
6. Save, Activate, and close the UI Designer. Now, your screen will pop-up the mandatory asterisk on the Incident Category field any time you try to select the “AS” Service Category and Save, as shown below:
Even if the code works now, we cannot deploy something with some hard-coded constant string inside. In this section we will define the right Business Configuration for the solution: our purpose has been to store all the Service Category codes into a customizing table, which could be published as a Fine-Tuning activity in the Cloud 4 Customers Implementation Configuration.
The steps are the following:
1. We started creating a new Business Configuration Object in the Solution. The Object has been created with the name SERVICECATEGORYLIST.bco and just a field called SERV_CAT, as shown in the picture below:
2. From the BCO, we created the Business Configuration Set, with the following data inside:
3. From the BCO, we created a Business Configuration View, for the End-User customizing, and attached the Quick view to the SAP Cloud 4 Customers Implementation Project WorkCenter, as described in the SAP Application Studio Help Guide:
a. In the Configuration Explorer, open the Implementation Projects work center view by opening the /SAP_BYD_APPLICATION_UI/BCTools/WorkCentre/ folder. The file name of the view is ImplementationProjects_WCView.WCVIEW.uiwocview.
b. In the Extensibility Explorer, select the ImplementationProjects_WCView.ao.uianchor anchor and click Assign Component to View.
c. In the Type field, select NavigationTarget.
d. In the Component field, select your BC view from the Repository. It is stored in the following folder: [name of your solution]_BC] → SRC → [your BC view].
e. Click OK and Apply.
You can find the name of your solution in the studio: In the Solution Explorer, select your solution. In the Properties, in the Project File field, there is the name of your solution. |
f. Save and activate your UI and close the UI designer.
4. In order to create a new activity in the Fine-Tuning, we then created a new Business Adaptation Catalog, called “Mandatory Incident Category for Service Category” in the solution. The Catalog has the following specs:
5. Then Activate every object created and Deploy the solution in the Cloud system.
With the same logic it is possible to bind and then control the behaviour of the UI Embedded Components for a more complex View (for instance the tabs of a WorkCenter), in order to achieve our goal.
The solution is based on the following components:
· A new Business Object (linked to the ServiceRequest) with the data specific for the Social Tab;
· A new Embedded Component (called “SOCIAL”) to attach to the Ticket TI screen as a Tab;
· A new logic for controlling the EC by the Service Category field.
The following section describe the single components in details.
In order to create an Embedded Component specific for the Social information, the Business Object WebServiceSocial_DataContextBO.bohas been created with the following specs:
import AP.Common.GDT as apCommonGDT;
import AP.CRM.Global;
businessobject WebServiceSocial_DataContextBO {
[Label ("Count of Social Interactions")] elementSocialInteractionCount:IntegerValue;
[Label ("Most Active Social Network")] element MostActiveSocialNetwork:LANGUAGEINDEPENDENT_EXTENDED_Text;
[Label ("Interaction reference")] elementInteractionReference:LANGUAGEINDEPENDENT_LONG_Text;
[Label ("Ticket ID")] elementTicketID:BusinessTransactionDocumentID;
associationRefServiceRequest to ServiceRequest;
}
The association statement will let us to link the new Business Object as a child node of the Service Request BO.
Furthermore, the main Business Object Extension for the ServiceRequest BO has been enhanced with a new control flag/indicator field:
[Label ("Social Tab")] element flgSocialTab:Indicator;
The steps for creating a new EC and linking it to the Ticket Workcenter as a new Tab are described below:
1. On the Add --> New Item functionality, select the item Embedded Component, as shown below:
2. After giving it a name (in our case: SocialTab_EC1.EC.uicomponent) and pressing Add button, open it via the UI Designer and add inside some of the fields defined inside the WebServiceSocial_DataContextBO BO:
3. Save and activate the new EC.
4. Select the main Business Object Extension, and Enhance Screen from the Contextual Menu:
5. The screen to enhance by adding the new Tab is the COD_SEOD_Agent_Workspace_TI:
6. Open the screen in the UI Designer, and select the Undefined level in the Extensibility Explorer view:
7. Select the button Add View with embedded component, and fill the pop-up window form with the following information:
a. Tab Title: “SOCIAL”
b. Embedded Component: the following:
8. Back in the Extensibility explorer view, select the button Adjust propertiesand bind the new tab to the field flgSocialTab:
9. Finally, Save and Activate the edited screen.
The logic for controlling the new flgSocialTab flag (and then the whole Tab) will be added in the following ServiceRequest BO Event Handlers:
· BeforeSave: in the case the User creates a new Ticket with the Service Category “SS”;
· AfterModify: in the case he changes the value from any to “SS” directly on the Ticket TI screen.
The code snippets for both are composed by the following lines:
var tktServiceCat= this.ServiceTerms.ServiceIssueCategoryCatalogueCategoryKey.ServiceIssueCategoryID;
if (!tktServiceCat.IsInitial()) {
var bcoServICList = SR_MANDATORY_INFORMATION.QueryByElements.Execute();
var isPresentInConf = false;
var bcoServiceCategory;
foreach(var bcoServICItemin bcoServICList) {
if(bcoServICItem.SERV_CAT.content == tktServiceCat.content) {
isPresentInConf= true;
bcoServiceCategory= bcoServICItem;
}
}
if (isPresentInConf) {
/* core logic start */
if(bcoServiceCategory.SOCIAL_TAB == true) this.flgSocialTab= true;
elsethis.flgSocialTab= false;
/* core logic end */
}
} else {
this.flgSocialTab = false;
}
In the end, the final result is shown in the picture below:
The same effect is not present for the Service Category “Social Support”, where we are able to save successfully a new Ticket even without specifying an Incident Category:
Furthermore, it is interesting to check that for the Category SS the tab “Social” has appeared:
Then, if we change the Category from SS to AS, the Tab disappears again:
I am Davide De Luca, and at present time I work as a Senior Consultant at Bluefin Solutions Ltd for Manufacturing Business Process, coming from several work experience as IT Specialist and SAP CRM Consultant in Capgemini, E-Utile – an ATOS WorldGrid Company and in Accenture (Rome office).
I can offer a consistent experience on System Integration oriented on the Engineering of new and innovative services and solution for small/medium and big Enterprises based on SAP Product and Services. My experience in this market is such of 8 years.
In details, I have been reaching gradually the following skills:
More information about Bluefin Solutions at: http://www.bluefinsolutions.com/
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
4 | |
4 | |
4 | |
3 | |
3 | |
3 | |
3 | |
3 | |
3 | |
2 |