Product Information
Power of Business Add-Ins in SAP S/4HANA Cloud
In this series of blogs, I am going to share about the use-case based implementations of Cloud BAdis in SAP S/4HANA Cloud.
For this purpose, I have taken those SAP S/4HANA Cloud BAdis which are popular among many of our Customers.
There would be 3 major key learnings for you in this blog:
How to implement a BAdi?
How to consume CDS views in a BAdi?
How to write the business logic for Approver determination?
Timesheet Approver Determination BAdi:
Default functionality of Timesheet Approval:
We are aware that, the Timesheet Approver for CPM Projects is the Project Manager by default.
But there are 2 cases in which a Project Manager gets his/her own time sheet for approval (self-approval) in the standard case:
1- When a Project Manager is also one of the Consultants contributing to the same project and submits his Timesheet for consulting efforts.
2- When Project Manager submits his own time sheet for billing of Project Management efforts.
Although this is an intended functionality, but it is given with the flexibility of customization i.e. we may define who would be the Approver.
Customization using BAdi:
Most of our Professional Services Customers want to customize this behavior by making one of the other project stakeholders as Approver when Project manager submits his Timesheet.
There can be many such scenarios where the Approver needs to be defined by Customers based on different criteria.
Let us look into the details of how we make Project Partner as the Approver of Project Manager’s Timesheet via Timesheet Approver Determination BAdi:
First, let’s implement the Timesheet Approver Determination BAdi and then we will test it.
Note: This BAdi gets called only when the approval scenario is enabled in the configuration app ‘Maintain Data Entry Profiles’ for Timesheet.
Step1: Go to Custom Fields and Logic App, navigate to custom logic tab and Create New Enhanced Implementation.
Step2: Select Business Context – ‘HCM- Timesheet Approver Determination’, BAdi Description and give a name to your implementation.
Step 3:
Insert the below code snippet under logic:
IF timeentry-wbselement IS NOT INITIAL.
SELECT SINGLE _engagementprojfinancialplan_engagementproject-engagementproject
FROM i_workpackage
WHERE workpackage = @timeentry-wbselement
INTO @DATA(lv_eng_project).
SELECT ProjectManager FROM I_EngagementProject
UP TO 1 ROWS
INTO @DATA(lv_project_manager)
WHERE EngagementProject = @lv_eng_project.
ENDSELECT.
IF timeentry-personworkagreement = lv_project_manager.
SELECT EMPLOYMENTINTERNALID FROM i_engagementprojectroles
INTO @DATA(lv_project_partner)
UP TO 1 ROWS
WHERE EngagementProject = @lv_eng_project AND EngagementProjectRole = ‘P004’.
approverperson = lv_project_partner.
ENDSELECT.
ENDIF.
ENDIF.
Let’s understand what happens in above code:
– First, we identify the Engagement Project using the CDS view I_workpackage
– Then we identify the Project Manager of this Project using CDS view I_engagementproject
– When the project manager is the person assigned to work agreement, we determine the Project Partner of this Project using CDS view i_engagementprojectroles
– The Project Partner is then assigned as the Approver person
Step 4: Save the logic and Publish it.
Step 5: You should see a success message stating successful publishing of your BAdi.
In the second part, let us test this BAdi:
The below video showcases the behavior after implementation of BAdi and here are the key things to notice it:
Anjani Kumar Mishra is the Project Manager and Consultant who submits his Timesheet and it goes for approval to Project Partner as coded in our BAdi.
Akshay Kumar is Project Partner who gets the Timesheet for approval in his inbox and approves it.
Great video! Thanks for sharing this custom logic scenario
informative. thanks
Great article! Could we use the same logic for an ePPM (enterprise) project? I am not sure whether we could retrieve the project manager from there.
That's what we're trying right now! Do you have more information in the meanwhile?
Christopher Linke We have recently managed to retrieve it in a BAdI, but it does require several CDS views. By using the following views you can retrieve the project manager: I_EnterpriseProject, I_EnterpriseProjectRole, I_EntProjectEntitlement, I_EnterpriseProjectTeamMember.
Thanks! How do you identify if it is an ePPM project though?
Hi Esmee Peet ,
I found the path to determine the project manager. But the BADI wants the "Personnel number" of the project manager and I haven't found a way to get it!? It's not part of the project specific tables and all employee tables I found are not released. Your help would be very much appreciated.
Cheers,
Chris
Hi Christopher,
We use the following code:
** Check whether timewriting is on a project
IF timeentry-wbselement IS NOT INITIAL.
* Get project UUID from project element
Select Single ProjectUUID FROM I_EnterpriseProjectElement
Where ProjectElement = @timeentry-wbselement
INTO @DATA(project_uuid).
* If the wbs is not an element, get project UUID from project header
if project_uuid is initial.
Select Single ProjectUUID FROM I_EnterpriseProject
Where Project = @timeentry-wbselement
INTO @project_uuid.
endif.
* Get the UUID for the project manager role of the project
Select Single ProjectRoleUUID FROM I_EnterpriseProjectRole
Where ProjectUUID = @project_uuid AND ProjectRoleType = 'YP_RL_0001'
INTO @DATA(project_role).
* Get the UUID for the team member who is the project manager
Select Single TeamMemberUUID FROM I_EntProjectEntitlement
Where ProjectRoleUUID = @project_role
INTO @DATA(teammember_uuid).
* Get the UUID for the business partner of the project manager
Select Single BusinessPartnerUUID FROM I_EnterpriseProjectTeamMember
Where TeamMemberUUID = @teammember_uuid
INTO @DATA(BP_uuid).
* Get the personnel number of the project manager
Select SINGLE PersonWorkAgreement FROM YY1_employee_ID
WHERE BusinessPartnerUUID = @BP_uuid
INTO @DATA(approver_projectmanager).
I hope this helps.
Regards,
Esmee
Awesome, thank you so much! I was looking for the column/datatype "personnelnumber" and coudn't find anything
@Akshay Kumar
FIELD-SYMBOLS: <tkomv> TYPE ANY TABLE.
data xkomv_tab type TAB_KOMV.
DATA(komv_va) = '(SAPMV45A)XKOMV[]'.
ASSIGN (komv_va) TO <tkomv>.
IF sy-subrc IS INITIAL AND <tkomv> IS ASSIGNED.
xkomv_tab = <tkomv>.
UNASSIGN <tkomv>.
SORT xkomv_tab BY kschl.
ENDIF.
ASSIGN (komv_va) TO <tkomv>. will getting error message from Cloud as "The addition 'dynamic-object' in the restricted language scope".