Bisher kenne ich keine “offizielle” Klasse der SAP für die Sachbearbeiterermittlung. Auf jedem System dafür eine neue Helper Klasse/Methode anzulegen finde ich aber auch nervig. Ich nutze daher diese Klasse aus dem Notification Tool Paket P99_NT, nicht optimal, erfüllt aber seinen Zweck.
I had to create an E-Mail template where I did not need a CDS view or any variable at all. I simply needed the defined mail template without any rendering of class cl_smtg_email_api. Solution: Reading the plain mail template can be achieved using class cl_smtg_email_template and method get_tmpl_cont:
Gerade einen hilfreichen Trick gelernt, wie man den Namen einer Tabelle ermitteln kann. Angenommen man ist in der SPRO unterwegs und möchte den Namen der zugehörigen Tabelle des Customizingschritts ermitteln, kann man versuchen über F1 → Technische Info → Tabellenname den Namen zu finden. Häufig steht dort allerdings nur der View-Name, und der muss nicht zwangsläufig den Namen der Tabelle enthalten. Ein Fall wie V_T77PT_OVT_APPL ist einfach, da man nur V_ entfernen muss für den Tabellennamen T77PT_OVT_APPL. Falls man es aber nicht aus dem View-Namen ableiten kann, einfach in der Transaktion SM12 nach den Sperreinträgen zu dem eigenen User schauen. Dort findet man in der letzten Spalte Sperrargument den Tabellennamen. Die Tabelle muss dafür natürlich in einem anderen Modus noch geöffnet sein.
Beim Einrichten der 1-Stufigen Genehmigung von Urlaub mit dem Standard Workflow 21500001 bin ich in folgenden Fehler gelaufen in der Inbox nach Drücken des Genehmigungsbuttons.
Merkwürdigerweise wurde der Urlaubsantrag erfolgreich genehmigt und trotzdem gab es eine Fehlermeldung. Nach kurzem debuggen war auch klar warum. Der Antrag wurde erst erfolgreich genehmigt und dann wurde das gleiche Coding nochmal durchlaufen und führte zu einer Kollisionsmeldung.
Daraufhin habe ich mir den BAdI /IWWRK/BADI_WF_BEFORE_UPD_IB angeschaut. Dort konnte ich zwei Implementierungen zum Thema Leave Approval finden und in beiden war der Workflow 21500001 als Filterkriterium eingetragen. Das erklärte, warum die Genehmigungslogik zweimal durchlaufen wurde.
Daraufhin habe ich nach einem Hinweis gesucht und folgenden gefunden: 2658528. Der beschreibt zwar eine andere Fehlermeldung, aber die Lösung war genau die Aussage, die ich gesucht habe.
Die Implementierung HRMSS_LEAVE_APPROVAL musste also deaktiviert werden. Ich habe das über die SE19 gemacht, auch wenn das bedeutete, dass ich nun als letzter Änderer eines SAP-Objekts drin stehe. Anscheinend geht es auch über den Funktionsbaustein ENH_BADI_IMG_ACTIVITY_TOGGLE wie hier beschrieben.
It took me some time to figure out, how I can provide a label for an action parameter.
I try to separate all my translations in label.cds file. This means, the annotations are not placed where the entities or actions are defined. If you have the action definition and the label annotations in one file, you could simply do the following for an action:
trip-service.cds
entity Trip as projection on db.Trip
actions {
action approval();
action rejection(reason: String @title: '{i18n>reason});
};
But if you separate both, you need to access somehow the defined action to add the annotation. Following a short snippet, how it works. The important part is, that you have to write a complete new annotation block for your actions.
trip-service.cds without label
service tripService @(requires: 'authenticated-user') {
entity Trip as projection on db.Trip
actions {
action approval();
action rejection(reason: String);
};
}
label.cds
using my.namespace as db from '../db/index';
using tripService from '../srv/trip-service';
annotate db.Trip with @title: '{i18n>trips}' {
description @title : '{i18n>description}';
status @title : '{i18n>status}';
// etc.
}
// solution
annotate tripService.Trip actions {
rejection(reason @titlel: '{i18n>reason}' )
}
I had the task to insert additional vacation days to the TimeAccount of some employees. To do this, you have to insert some new entries in the related TimeAccountDetail entity.
But to me, it was unclear, what I have to provide as externalCode. Obviously, TimeAccount_externalCode required the externalCode of the TimeAccount, which the entry should belong to. But I was expecting that the TimeAccountDetailexternalCode should be created, when UPSERTing the entry. Somehow the documentation is missing some explanation here… But in the note 2243841 I found the missing hint:
While using API calls, Successfactors system would not generate unique external Code for TimeAccountDetail API. You will have to explicitly provide external code which should be unique.
Ok, so simply provide a random externalCode. Following my UPSERT Request:
### The related TimeAccount, where the entry should belong to. Can be fetched via another API call
@TimeAccount_externalCode=aac183cdc57242cb9f7454131f0da069
### Create a random TimeAccountDetail externalCode
@externalCode=70b54990b44440fab4c5084c971cc744
### Insert balances
GET {{$dotenv sf_api_url}}/odata/v2/upsert
Authorization: Basic {{$dotenv sf_api_auth_base64}}
Accept: application/json
Content-Type: application/json
{
"__metadata" : {
"uri" : "http://my-sf-demo-api-server/odata/v2/TimeAccountDetail(TimeAccount_externalCode='{{TimeAccount_externalCode}}',externalCode='{{externalCode}}')",
"type" : "SFOData.TimeAccountDetail"
},
"TimeAccount_externalCode" : "{{TimeAccount_externalCode}}",
"externalCode" : "{{externalCode}}",
"bookingUnit" : "DAYS",
"bookingType" : "MANUAL_ADJUSTMENT",
"bookingDate" : "\/Date(1747872000000)\/",
"bookingAmount" : "1",
"comment" : "Urlaub"
}
But what ever I tried as externalCode, it always failed…
We generally do not suggest to use Upsert operation for TimeAccountDetail OData API due to external code limitation.
This confused me even more, but as the note is from 2016, I thought it could be outdated, and the official API documentation is correct. But it seems the opposite is right…. When trying a normal POST instead of an UPSERT, it immediately worked.
### The related TimeAccount, where the entry should belong to. Can be fetched via another API call
@TimeAccount_externalCode=aac183cdc57242cb9f7454131f0da069
### Create a random TimeAccountDetail externalCode
@externalCode=70b54990b44440fab4c5084c971cc744
### Insert balances
POST {{$dotenv sf_api_url}}/odata/v2/TimeAccountDetail
Authorization: Basic {{$dotenv sf_api_auth_base64}}
Accept: application/json
Content-Type: application/json
{
"TimeAccount_externalCode" : "{{TimeAccount_externalCode}}",
"externalCode" : "{{externalCode}}",
"bookingUnit" : "DAYS",
"bookingType" : "MANUAL_ADJUSTMENT",
"bookingDate" : "\/Date(1747872000000)\/",
"bookingAmount" : "1",
"comment" : "Urlaub"
}
Not sure if I did something wrong when using UPSERT, but why should I even use an UPSERT, if I can simply use a normal POST request. Once again, poor SAP documentation has cost me a lot of my lifetime…