As promised in my previous blog
"Organizational Changes: Implementing Custom Rules for Profit Center Derivation", I am enhancing it with a series of example implementations. Here is the first one, which is from a real-world customer request.
The task
In a call, I got this request by a customer, which can be perfectly answered with a custom rule:
For orders, we are fine with the default profit center inheritance. But for maintenance orders, we want to derive the profit center from their responsible cost center. This means, if we change the profit center for a cost center, we need to change maintenance orders using it as responsible cost center as well.
From release 2022, we are offering organizational changes with the capability to change the profit center on orders. Maintenance orders have, so far no default derivation implemented and need to be added manually in the app (March 2023). Nevertheless, base views are already offering maintenance orders for change in a custom implementation. So, we're ready to go for a BAdI implementation.
The solution
So, I'd like to draft what you need to do at first and then go into details.
- At first, please make sure that your system is up to date on regards to SAP notes. At least for the 2022 release, some notes have been published to correct or also to round up organizational changes and the BAdIs. This example requires implementation of SAP note 3311946.
Assuming this topic is covered by your SAP administrator, this is not described here (we are developers, aren't we?).
- We need a custom CDS view that identifies the orders subject to change.
- We will write an implementing class for BAdI definition FINOC_RULE_ORD_ENH.
- Also, a BAdI enhancement implementation is needed to consume the implementing class. This won't be explained here.
Implementing the custom CDS view
So, here's more detail on how to solve the request with a new CDS view which will return a result set that needs no further iteration in ABAP code:
- Implementing the default profit center inheritance. This is the easiest part. We will reuse the default implementation (which can be found in FINOC_RULE_ORD_DEFAULT), and just "loop through" fields without changes - but exclude maintenance orders. Today, maintenance orders (aufk~autyp = '30') are not part of this default view, but in future, this could be the case. So, we should restrict the result to avoid duplicates.
- Implementing a new profit center inheritance for maintenance orders only. Luckily, we can reuse the pre-delivered base view and join it with the runtime table of cost centers.
- The base view delivers us all orders multiplied with all instances of open organizational changes. All fields that we need later are correctly filled already, as we can see when opening the base view in ABAP Development Tools (ADT) or in the first part of the view.
- The runtime table for cost centers gives us all cost centers that are part of an organizational change. So we join the cost centers (key is accounting area plus cost center) and organizational change fields to get all open, i.e. currently relevant changes on cost centers, for those cost centers that are used in orders as responsible cost centers.
- The list of fields looks similar to those of the first view - with one exception. We retrieve profit center new ("prctr") from the cost center runtime.
- In the where part there's a comparison of cost centers and orders old profit centers. This is to make sure that we change only those orders that have inherited their old profit center obviously from the cost center. To understand how to calculate the old profit center in a case where the base view cannot be used, take a closer look to base view FINOC_RULE_ORD_BASE.
Here's the view we end up with. It's easier to read than expected.
@AbapCatalog.sqlViewName: 'Z_FINOC_MNTNC'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Example implementation maintenance order'
define view ZTM_OC_EXMPL_MAINTENANCE_ORDER as
select from FINOC_RULE_ORD_DEFAULT
{
key aufnr,
key orgl_change,
kokrs,
bukrs,
prctr_old,
prctr,
autyp,
prctr_drvtn_source_type,
srce_werks,
srce_matnr,
srce_kostl,
srce_ps_psp_pnr,
srce_ps_prj_pnr,
objnr
}
where autyp <> '30' // no maintenance orders
union all
select from FINOC_RULE_ORD_BASE as ord
inner join finoc_rt_ccr as cctr // cost center runtime table
on cctr.orgl_change = ord.orgl_change
and cctr.kokrs = ord.kokrs
and cctr.kostl = ord.kostv
{
key ord.aufnr,
key ord.orgl_change,
ord.kokrs,
ord.bukrs,
ord.prctr_old,
cctr.prctr,
ord.autyp,
ord.prctr_drvtn_source_type,
ord.srce_werks,
ord.srce_matnr,
ord.srce_kostl,
ord.srce_ps_psp_pnr,
ord.srce_ps_prj_pnr,
ord.objnr
}
where ord.autyp = '30' // only maintenance orders
and cctr.prctr_old = ord.prctr_old // "... original profit center of cost center matches those of the order
Implementing class
The implementing class is used in the enhancement implementation. The only relevant part is in method change_cds_name, where we set the changing parameter to the CDS view name we've defined before. Method change_cds_result can stay empty - the whole calculation has already happened at database level.
CLASS ZCL_OC_EXMPL_MAINTENANCE_ORDER DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES:
if_badi_interface,
if_finoc_rule_enh.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZCL_OC_EXMPL_MAINTENANCE_ORDER IMPLEMENTATION.
METHOD if_finoc_rule_enh~change_cds_name.
cv_cds_view = 'ZTM_OC_EXMPL_MAINTENANCE_ORDER'
ENDMETHOD.
METHOD if_finoc_rule_enh~change_cds_result.
ENDMETHOD.
ENDCLASS.
Conclusion
We've seen that it is easy to implement a BAdI for Organizational Changes when the base view delivers the fields that are needed. You've learned the importance of comparing the old profit centers when writing own profit center inheritance rules and how you can combine the default behaviour with a custom-defined one.