Success Factors - updating custom Picklists - python

Using Postman Version 7.34.0 (7.34.0)
Technically I am using Django / Python in my application, but I am testing using Postman, I will use the same payload while making a call to the Success Factors ATS.
The documentation for SuccessFactors: link
I am trying to update a Candidate entity, in particular a custom Picklist, with custom PicklistOptions on that Candidate entity.
I was given a list of values for each Picklist, like this one:
Field ID: "myCustomPicklist" (used as name field in the payload)
Field label: Some Label (irrelevant - used for UI display)
Field Type: Picklist
And for each option of the Picklist:
...
PicklistOption value: <Str, "some_value"> (value string displayed in the UI)
PicklistOption external code: <Str, "picklistOption_external_code">
PicklistOption external ID: <Int, picklistOption_id >
...
I was able to update the Picklist field on the candidate using the PicklistOption external IDs, this way:
POST: https://<subdomain>.successfactors.eu/odata/v2/upsert
Payload:
{
"__metadata": {"uri": "Candidate(<candidate_id>)"},
"firstName": "some_name",
"lastName": "some_last_name",
...
"myCustomPicklist": {
"__metadata": {"uri": "PicklistOption('<picklistOption_id>')"},
"optionValue":"<picklistOption_id>"
}
}
Response:
...
<d:status>OK</d:status>
<d:editStatus>UPDATED</d:editStatus>
<d:message>Candidate has been updated successfully</d:message>
<d:index m:type="Edm.Int32">0</d:index>
<d:httpCode m:type="Edm.Int32">204</d:httpCode>
...
The problem:
I understand that the PicklistOption.external-id is the ID from the DB, and that means that I would have to get a different ID to interact within different environments - that would force me to create a special map, and I wouldn't want that.
My question:
How can I use the picklistOption_external_code instead?
I am looking for the right syntax, as I was not able to find it in the documentation.
That would allow me to have a single map of fields, as the code (naming) will not change between environments, while the IDs will change.
Thank you!
EDIT 1
This works:
"myCustomPicklist": {
"__metadata": {"uri": "PicklistOption('<picklistOption_id>')"},
"externalCode":"<picklistOption_external_code>"
}
But I cannot find the syntax for replacing the last occurrence of the picklistOption_id in the metadata
EDIT 2
This also works. Well, almost:
"myCustomPicklist": {
"__metadata": {"uri": "PicklistOption('<PicklistOption_value>')"},
"externalCode":"<picklistOption_external_code>"
}
This seems to pass the validation:
<d:message>Candidate has been updated successfully</d:message>
The PicklistOption_value is a legitimate descriptor for the PicklistOption - but the UI in SuccessFactors seems to override the displayed content for the field with null value.
I verified that if I use a fake PicklistOption_value I see an error:
<d:message>Candidate upsert failed: myCustomPicklist invalid, with the index 0</d:message>

For any given SAP SuccessFactors entity (table), the way the picklist has to be used with either OptionID or externalCode is predefined by SAP in the product.
Use the OData Dictionary for the entity, and for the field's navigation data, check the Type column. It will be either: PicklistOption or PickListValueV2.
See SAP KBA 2773713: https://launchpad.support.sap.com/#/notes/2773713
As you noted, if using OptionID, then your solution must account for different number values in different SuccessFactors instances.

Related

Get all fields from AdsInsights on Python Facebook SDK

I'm using Facebook's Python SDK to extract Ads Insights, but I can't find the right way to retrieve ALL fields without having to declare them, which is pretty cumbersome.
My current code looks like this:
ads = tempaccount.get_insights(
params={'date_preset': 'yesterday',
'level': 'ad'},
fields=[AdsInsights.Field.account_id,
AdsInsights.Field.account_name,
AdsInsights.Field.ad_id,
AdsInsights.Field.ad_name,
AdsInsights.Field.adset_id,
AdsInsights.Field.adset_name,
AdsInsights.Field.campaign_id,
AdsInsights.Field.campaign_name,
AdsInsights.Field.cost_per_outbound_click,
AdsInsights.Field.outbound_clicks,
AdsInsights.Field.spend])
Is there a way to force the "fields" attribute to bring all possible fields without declaring them?
Unfortunately, you will need to specify all the required fields. It's not possible to get all fields without explicitly specifying them.
My code also looks similar to yours when querying the insights endpoint.
This worked for me:
from facebookads.adobjects.adsinsights import AdsInsights
for property, value in vars(AdsInsights.Field).items():
print(property, ":", value)
Got from this post: How to enumerate an object's properties in Python?

Setting Extended Properties in Microsoft Graph API using proptags

I am trying to set a property tag according to Graph API documents as stated here: https://learn.microsoft.com/en-us/graph/api/resources/extended-properties-overview?view=graph-rest-1.0
I am trying to set a extended property on a MailFolder using the patch endpoint as listed here: https://learn.microsoft.com/en-us/graph/api/mailfolder-update?view=graph-rest-1.0&tabs=http
The content of the message is:
{'singleValueExtendedProperties': [{'id': 'String 0x10F4000B', 'value': 'true'}]}
However, i always get the result that indicates it fails due to a property value error:
{"error": {"code": "ErrorFolderSavePropertyError", "message": "The folder save operation failed due to invalid property values.", "innerError": { "request-id": "GUID", "date": "2019-11-12T19:44:02"}}}
Looking at the rules around MAPI and setting its values, it is trying to set the tag 0x10F4 using type 0x000B which is boolean. However, the extended properties only excepts strings. I am not sure how to set a boolean value into the value field.
the second half for the type goes where the string value is. So to post this, it will become
`{'singleValueExtendedProperties': [{'id': 'boolean 0x10F4', 'value': '**true**'}]}1

Work with nested objects using couchdb-python

Disclaimer: Both Python and CouchDB are new for me. So far my "programming" has mostly consisted of Bash scripts.
I'm trying to create a small script that updates objects in a CouchDB database. The objects however aren't created by my script but by an App called Tap Forms that uses CouchDB for sync. Basically I'm trying to automatically update the content of the app. That also means I can't really influence the structure or names of the objects in CouchDB.
The Database is mostly filled with objects of this structure:
{
"_id": "rec-3b17...",
"_rev": "21-cdf6...",
"values": {
"fld-c3d4...": 4,
"fld-1def...": 1000000000000,
"fld-bb44...": 760000000000,
"fld-a44f...": "admin,name",
"fld-5fc0...": "SSD",
"fld-642c...": true,
},
"deviceName": "MacBook Air",
"dateModified": "2019-02-08T14:47:06.051Z",
"dateCreated": "2019-02-08T11:33:00.018Z",
"type": "frm-7ff3...",
"dbID": "db-1435...",
"form": "frm-7ff3..."
}
I shortened the numbers a bit and removed some entries to increase readability.
Now the actual values I'm trying to update are within the "values" : {...} array (or object, or list, guess I don't have much experience with JSON either).
As I know some of these values, I managed to create view that finds the _id of an object on the server. I then use the python-couchdb module as described in documentation:
for item in db.view('CustomViews/test2', key="GENERIC"):
doc = db[item.id]
This gives me the object. However I want to update one of the values within the values array, lets say fld-c3d4.... But how? Using doc['values'] = 'new_value' updates the whole array. I tried other (seemingly logical) ways along the lines of doc['values['fld-c3d4']'] = 'new_value' but couldn't wrap my head around it. I couldn't find an example in any documentation.
So here's a example how to update the fld-c3d4.
You have your document that represent a dictionary with nested dictionary.
If you want to get the values, you will do something like this:
values = doc['values']
Now the variable values points to the values in your document.
From there, you can access a sub value:
values['fld-c3d4'] = 'new value'
If you want to directly update the value from the doc, you just have to chain those operations:
doc['values']['fld-c3d4'] = 'new value'

pact: how to check a a field in the response that may or may not exist

I have a service that will respond to a request with a json blob, such as this:
{
"field1": 1,
"field2": "2",
"array": [1,2,3]
}
I know that I can test array by using EachLike, like this:
expected = {
"field1": Like(1),
"field2": Like("2"),
"array": EachLike(1)
}
The issue is that "array" is an optional field in the response. It may not exist at all, and if it doesn't, I still need the contract to validate. How do I define that a field in the response body must match a type if it exists, but that it may not exist at all?
From https://github.com/pact-foundation/pact-ruby/wiki/FAQ#why-is-there-no-support-for-specifying-optional-attributes
Why is there no support for specifying optional attributes?
Firstly, it is assumed that you have control over the provider's data (and consumer's data) when doing the verification tests. If you don't, then maybe Pact is not the best tool for your situation.
Secondly, if you think about it, if Pact supports making an assertion that element $.body.name may be present in a response, then you write consumer code that can handle an optional $.body.name, but in fact, the provider gives $.body.firstname, no test will ever fail to tell you that you've made an incorrect assumption. Remember that a provider may return extra data without failing the contract, but it must provide at minimum the data you expect.
I would recommend that you write one interaction where you require that the array is populated, so that you know how to deal with a populated array. Then leave it out of the other interactions altogether, and then it won't matter whether it's populated or not.

How to build "Tagging" support using CouchDB?

I'm using the following view function to iterate over all items in the database (in order to find a tag), but I think the performance is very poor if the dataset is large.
Any other approach?
def by_tag(tag):
return '''
function(doc) {
if (doc.tags.length > 0) {
for (var tag in doc.tags) {
if (doc.tags[tag] == "%s") {
emit(doc.published, doc)
}
}
}
};
''' % tag
Disclaimer: I didn't test this and don't know if it can perform better.
Create a single perm view:
function(doc) {
for (var tag in doc.tags) {
emit([tag, doc.published], doc)
}
};
And query with
_view/your_view/all?startkey=['your_tag_here']&endkey=['your_tag_here', {}]
Resulting JSON structure will be slightly different but you will still get the publish date sorting.
You can define a single permanent view, as Bahadir suggests. when doing this sort of indexing, though, don't output the doc for each key. Instead, emit([tag, doc.published], null). In current release versions you'd then have to do a separate lookup for each doc, but SVN trunk now has support for specifying "include_docs=True" in the query string and CouchDB will automatically merge the docs into your view for you, without the space overhead.
You are very much on the right track with the view. A list of thoughts though:
View generation is incremental. If you're read traffic is greater than you're write traffic, then your views won't cause an issue at all. People that are concerned about this generally shouldn't be. Frame of reference, you should be worried if you're dumping hundreds of records into the view without an update.
Emitting an entire document will slow things down. You should only emit what is necessary for use of the view.
Not sure what the val == "%s" performance would be, but you shouldn't over think things. If there's a tag array you should emit the tags. Granted if you expect a tags array that will contain non-strings, then ignore this.
# Works on CouchDB 0.8.0
from couchdb import Server # http://code.google.com/p/couchdb-python/
byTag = """
function(doc) {
if (doc.type == 'post' && doc.tags) {
doc.tags.forEach(function(tag) {
emit(tag, doc);
});
}
}
"""
def findPostsByTag(self, tag):
server = Server("http://localhost:1234")
db = server['my_table']
return [row for row in db.query(byTag, key = tag)]
The byTag map function returns the data with each unique tag in the "key", then each post with that tag in value, so when you grab key = "mytag", it will retrieve all posts with the tag "mytag".
I've tested it against about 10 entries and it seems to take about 0.0025 seconds per query, not sure how efficient it is with large data sets..

Categories

Resources