a colleague of mine urged me to share this approach and I finally found some time to “write” (copy from my own internal documentation) this blog. As in my previous docs/blogs I am sharing the idea / the approach and some code-snippets but not every single bit of the coding. So, here goes. Have fun reading! 😉
About this blog
This blog will show an approach to protect paid receipts from alteration by the end user / traveler within WDYN FITE_VC_RECEIPTS in WDA Application FITE_EXPENSES which have not been imported by the Planning Submodule (FI-TV-PL) or the Credit Card Clearing (CCC) but have rather been entered manually by power users in the backend via PR05 or other means. Furthermore it simultaneously prevents the end user / traveler from creating paid receipts by himself. All this is achieved purely via pretty “neat” (judge for yourself) UI-Manipulation with means of a few snippets of generic coding, hence it is very straight-forward and does not delve deep into the standard, i.e. the chance of breaking stuff is vanishingly low.
Kudos to Michael Zwickl with whom I discussed my initial problem on the DSAG Forums and who led me into the right direction to implement a solution. 🙂
NW AS 7.03 ABAP Stack 731 Level 13, ECC 606 (EHP 6) with SAP_HR 604 Level 81 and EA_HR 607 (HR-Renewal 1) Level 32
In particular, the blog involves the following objects:
- WDA Application FITE_EXPENSES
- WDYN VCs FITE_VC_RECEIPTS and FITE_UI_RECEIPT_DETAILS
- BAdI TRIP_WEB_CHECK
We have been using FI-TV (Request and Expense Claims) including FI-TV-PL and CCC for quite some time now. Within our process cycle it can naturally happen that the company pays for certain things (partially in advance to the actual trip) and the technical consequence of this are receipts “already paid by the company”, i.e. V_T706B1 field PTKXX-CTRLREC = 2. Example:
These receipts are needed for the overall calculation of the trip’s expenses and further processing in FI, PY and the CCC, however they don’t invoke any reimbursement for the traveler.
In our company, the following requirements of receipt maintenance by the traveler had to be satisfied:
- the traveler must be able to create, modify and delete receipts that lead to a reimbursement (say a Taxi receipt)
- the traveler must not be able to modify or delete receipts that have been imported by the FI-TV-PL or CCC Submodules (the standard already covers this)
- the traveler must not be able to create, modify or delete paid receipts at all
Design flaw in the SAP standard (In my humble opinion)
The custom development I’m about to depict only came into existence because of one unnerving technical behaviour of the WDYN FITE_VC_RECEIPTS. It is generally possible, in several different ways, to restrict the Values of the Dropdown-Box for expense types, i.e. receipt types. Thus, the first idea that comes to mind when looking at the requirements is “delete those expense types from the value help”. Unfortunately, this is not possible, because every receipt that is published within the WDYN VC is validated against the context table of this very drop-down box. Yes, you heard right: All the receipts, including those that come from FI-TV-PL and CCC share the same fate.
This means, if you delete the paid receipts from the value help, they cannot be used within the Webdynpro UI anymore whatsoever. Even “funnier”, when importing a paid receipt from the CCC buffer that has an expense type excluded from the dropdown box for the user, the receipt becomes corrupted and blocks all means for FPM-navigations. On top, the corrupted receipt cannot be straightened out by the end user, since it is protected and read-only. All this is SAP standard.
Upon subsequently asking yourself the question “How do I restrict the value help without blowing the entire application to smithereens?” you’ll probably look like this:
Forgive the end users for they know not what they do
Since we went live with FI-TV before I created my custom development, the problem was still present. As a workaround we addressed this problem editorially. Even in doing so, of course the following personas of end users entered the stage:
Persona 1: The one who unintentionally deletes things
“Where did these receipts come from? Dammit, now I deleted them. Oh well, if they weren’t supposed to be deleted, then I wouldn’t have been able to do so.”
Persona 2: The one who intentionally deletes things
“What are these nonsensical receipts? Begone with ye!”
Persona 3: The one who accidentally creates paid receipts instead of “normal” receipts
“Where’s my reimbursement?!”
Persona 4: The one who abhors the new system and wants to see it burn
“Let’s change the amounts of those receipts a wee bit and let the developers search for an error in the system..”
After seeing that an editorial approach was not realistic, we proceeded to intercept all trips with paid receipts for manual audit before approval and subsequent settlement. However, since this also meant an increase in manual workload, it could only be considered a temporary workaround.
Getting straight to the point: The first thing I attempted to do was making all paid receipts read-only, no matter their origin. For this I used the BAdI “TRIP_WEB_CHECK” and implemented a bit of generic coding that searches within the field-control for “INPUT”-Fields which are used to determine whether a receipt is read-only or not. With this I hope that I never have to touch this again even when SAP introduces new fields, assuming they stick to their naming convention. The Methods used for this are IF_EX_TRIP_WEB_CHECK~USER_CHECK_LINE_OF_RECEIPTS and IF_EX_TRIP_WEB_CHECK~USER_CHECK_RECEIPTS. Note that both methods must inevitably be used because “Line of Receipts” is executed only at every action and/or roundtrip of the view and down/up-FPM-navigations whereas “check receipts” is executed only at forward/back-FPM-navigations. I.e. even though it first seems that using both methods at the same time is redundant, it actually isn’t.
This is not yet enough, though, because an end user can still create new paid receipts himself and use WDA actions which are not influenced by the field control of the receipt header. Thus, I created an enhancement in FITE_VC_RECEIPTS. With a few tweaks I disabled the buttons (in case of a selection of a paid receipt) and prevented the selection of paid receipts in the drop-down UI-Element by enhancing, respectively creating exits, for the methods ONACTIONEXPENSE_TYPE_SELECT, ONACTIONSELECT_RECEIPT and WDDOMODIFYVIEW of the View RECEIPTS_VIEW.
Only one thing left to do: The UI of the details of a receipt is not controlled via the field-control of the receipt-header, i.e. the implementation of the BAdI TRIP_WEB_CHECK have no effect on them. Instead the VC FITE_UI_RECEIPT_DETAILS, which is used in the Main View’s Table-Popin, must be enhanced.
All that needs to be done here is “ye good ol'” post exit for WDDOMODIFYVIEW and make literally everything read-only, in case a paid receipt is selected.
Here’s what it looks like from an end user’s perspective…:
…upon selecting a manually entered (by a poweruser in PR05) paid receipt:
…upon trying to create a new paid receipt:
Conclusion / Afterthought
We’ve been running this small development in production for about five months now and it seems extremely stable. Not even the earlier mentioned Persona #4 was able to lever it out.
Before going this way with the development I was trying to “abuse” the protection-flag of the field control to make the receipts “as if” they were from FI-TV-PL/CCC. However, this approach proved highly unstable due to much needed meddling with the Web Memory and other nasty side effects occuring in the backend (PR05).
Links to Information sources that can help understanding this document better:
|Overall Travel Management Process||Overall Process of Travel Management – Travel Management (FI-TV) – SAP Library|
|FI-TV Implementation Guide||http://help.sap.com/printdocu/core/Print46c/en/data/pdf/FITVPLAN/FITVGENERIC.pdf|
|WebDynpro ABAP Basics||Web Dynpro for ABAP: Tutorials for Beginners|
|WDA Expense Report and Receipts||SAP Library – Travel Management (FI-TV)|
That’s all, folks! I hope this is useful to somebody and you enjoyed reading! 😉