API Call from Custom field not showing the same data type - acumatica

Tried to do an API Call from a custom field that I published in one of our instance. The result value of the corresponding field didn't match the data type in our Data class. My field data type is Int but through the API, I got String instead. Also the field control element for this field is ComboBox
What I expect for the Kundengruppe value:
{
"id": "4b2758c6-8d86-4357-871e-70621d09719d",
"rowNumber": 3,
"note": null,
"Kundengruppe": {
"value": "1" //
},
"UUID": {},
"custom": {}
}
What I get:
{
"id": "4b2758c6-8d86-4357-871e-70621d09719d",
"rowNumber": 3,
"note": null,
"Kundengruppe": {
"value": "bis 25.000,- 0,00%" //
},
"UUID": {},
"custom": {}
}
ASPX & Data class attribute for custom field Kundengruppe
<px:PXDropDown runat="server" ID="CstPXDropDown40" DataField="UsrKundengruppe" CommitChanges="True" Enabled="True" SelectMethod="" />
------
[PXDBInt]
[PXIntList(new int[] {0,1,2,3,4,5,6,7,8}, new string[] {"bis 25.000,- 0,00%", "25.001,- bis 50.000,- 3,75%", "50.001,- bis 100.000,- 7,50%", "100.001,- bis 200.000,- 10,00%", "200.001,- bis 300.000,- 12,00%", "300.001,- bis 500.000,- 14,50%", "500.001,- bis 750.000,- 16,50%", "750.001,- bis 1.000.000,- 18,50%", "ab 1.000.000,- 20,00%"})]
[PXUIField(DisplayName="Kundengruppe Jahresumsatz von - bis Rabatt")]
Screenshots of some screens
Dropdown list, Element properties
Is there anyway to fixing this? I am not really familiar with C# in general. I also made a new fresh Endpoint to specifically for this custom field.
Note: I am using german localized version of Acumatica called Haufe x360

You need to set the data type on the web service endpoint screen, it defaults to string regardless of the column type:

I looked at the backend SQL Server tables for a stock PXDropDown (i.e. Shipping Rule property in Sales Order). If you set the Shipping Rule to "Ship Complete", then this sets "Ship Complete" in the database table as well. However, if you use a PXSelector, then the value is stored by reference in the database.
I don't think you are going to be able to do what you want to do with a PXDropDown. The framework doesn't have a way to go from the stored text database value back to the index value, and the REST API is just looking at what's in the database for the most part.
I would say change it to a PXSelector. Or you could write a graph extension that grabs the attribute values for the PXDropdown and saves the reference value to the database instead of the text value/saves it to another custom field (although you would have to make sure that the referential integrity will hold....for example if you add another dropdown value and that becomes value #1, then you've broken your referential integrity to the previous #1 value). The bottom line is that this can be done with a graph extension and a little bit of planning, but that will require C# code.

Related

Lowercasing complex object field names in azure data factory data flow

I'm trying to lowercase the field names in a row entry in azure data flow. Inside a complex object I've got something like
{
"field": "sample",
"functions": [
{
"Name": "asdf",
"Value": "sdfsd"
},
{
"Name": "dfs",
"Value": "zxcv"
}
]
}
and basically what I want is for "Name" and "Value to be "name" and "value". However can't seem to use any expressions that will work for the nested fields of a complex object in the expression builder.
I've tried using a something like a select with a rule-based mapping that is the rule being 1 == 1 and lower($$), but with $$ it seems to only work for root columns of the complex object and not the nested fields inside.
As suggested by #Mark Kromer MSFT, for changing case of columns inside complex type select the functions in the Hierarchy level.
Please check the below for your reference:
Here, I have used both.
You can see the difference in results.

Retrieve OptionSet from Dynamics Web API MetaData

I'm trying to retrieve the option set values (localized labels and integer Ids) for a specific field on a specific entity. Below is the code that I am using, but every time I execute it, it brings back ALL optionsets that are currently in my system (about 800+) and I don't want to do that.
EntityDefinitions(LogicalName='#MY_ENTITY#')/Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata?$select=LogicalName&$filter=LogicalName eq '#MY_ENTITY_ATTRIBUTE#'&$expand=OptionSet
maybe this can help,
/api/data/v9.1/ENTITY(guid OR Filter)?$select=ATTRIBUTE1,ATTRIBUTE2
include header:
{
"Prefer": "odata.include-annotations=OData.Community.Display.V1.FormattedValue"
}
this gives us a response like this:
{
"ATTRIBUTE1#OData.Community.Display.V1.FormattedValue": "Person",
"ATTRIBUTE1": 1,
"ATTRIBUTE2#OData.Community.Display.V1.FormattedValue": "Company",
"ATTRIBUTE2": 2
}
I'm using the stringmap entity to retrieve the optionsets.
This represents the optionsets as a simple table on which you can filter in the query
For example by calling:
/stringmaps?$filter=(objecttypecode eq 'contacts')
you get only the optionsets which are use in the contact entity. You can also filter on attribute name, the option value (field value) or option id (field attributevalue).

I am having trouble parsing the JSON in livecode

I'm trying to create a simple mobile app that queries an API and parses the response to display certain values.
The mobile has 2 fields viz:
Button to query the api
Large text box to display the contents
In my livecode stack, I've the following inclusions:
JSON Library
mergJSON
tsNet
The api response is as follows:
{
"data": [
{
"id": 1,
"date_created": "2021-11-08T17:12:03Z",
"date_updated": "2021-11-22T16:08:55Z",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe#unknown.com",
"phone": "9876543210",
"dob": "1980-01-01",
"password": "xxxxxxxxx",
"plan_start": "2021-11-22T16:07:46Z",
"plan_expiry": "2021-12-21T16:06:25Z"
}
]
}
I want to parse the JSON to display the email field value in the textbox.
In my livecode stack:
The button is named as "getdata"
The textbox is named as "flddata"
In the button script, I've added the following code:
put "<api url endpoint>" into tUrl
put "Authorization: Bearer xxxxxxxxx" into tHeaders
put tsNetGetSync(tUrl, tHeaders, tRecvHeaders, tResult, tBytes) into tData
put JSONToArray(tData) into tDataArray
put tDataArray["email"] into field "flddata"
But this doesn't work. Nothing happens. For the life of me, I can't figure out what's wrong. Any help would be appreciated. Thanks a ton!
To access the "email" key of the array that is built from the JSON you shared. You must first access the "data" key and then key 1. So the last line of your code would be as follows:
put tDataArray ["data"] [1] ["email"] into field "flddata"
Tips:
Put a break point on that line. This will allow you to see the contents of the variables so that you can see the structure of the array.
It looks like it might be a multidimensional array. Here's a simple way to get a look at how it's structured:
Drag a Tree View widget onto your card.
Set the arrayData property of the widget to your array tDataArray. Like this:
set the arrayData of widget "Tree View" to tDataArray
You should see the structure of the array in your tree view widget. It's possible that the array that was created looks something like this:
put tDataArray[1]["email"] into field "flddata"

Whats the best way to handle related data ids using Tabulator

Using Tabulator, if you have a 'select' editor and want it to link to values 'Male' and 'Female' but underneath male and female are values from another physical database table with id values of 1 and 2 (which are different than the 'row' id), whats the best way to do something like this?
The 'select' editor has ways to specify the display of items in the drop down and a literal display of the selected value, but no place for a hidden (not displayed) underlying ID of the selected value to pass when saving the data.
We could wrap the select data values in divs with a data attribute for the selects values ids and then pass that when updating, but are not sure this is the best option considering how Tabulator works. We could also just pass the raw selected value and then look it up on the server to get the associated ID, but that seems like a lot of overhead and tightly couples the server to the client, which wouldn't work for something like a 3rd party API where we have no server control.
Any thoughts on how best to handle something like this are appreciated!
The select editor allows for values to be passed in a number of ways, including specifying both the items value and its user visible label
If you want to show a different lable to the value you want to store, you can pass in an object, where the key of each property is the value that will be stored if it is selected, and the value of each property will be the lable displayed for it in the list.
{title:"Name", field:"name", editor:"select", editorParams:{
values:{
"steve":"Steve Boberson",
"bob":"Bob Jimmerson",
"jim":"Jim Stevenson",
}
}}
For more complex option lists you can use an array of objects, that allows you to define option groups, and disabled options.
{title:"Name", field:"name", editor:"select", editorParams:{
values:[
{ //option group
label:"Men",
options:[ //options in option group
{
label:"Steve Boberson",
value:"steve",
},
{
label:"Bob Jimmerson",
value:"bob",
},
]
},
{ //option group
label:"Women",
options:[ //options in option group
{
label:"Jenny Jillerson",
value:"jenny",
},
{
label:"Jill Betterson",
value:"jill",
},
]
},
{//ungrouped option
label:"Other",
value:"other",
},
]
}}
For full details on how to use this editor, checkout the Editor Documentation
Finally figured this out. You need to use the lookup formatter to display the text value using the same params as the select editor. This is not obvious since none of the select editor examples in the docs show use of it. Anyway, here is a simple example showing it in both directions. Of course you would want to abstract the data out instead of literally duplicating it, but here to help show the literal use, it is duplicated:
{
title:"Example",
field:"example",
editor: "select",
editorParams:{
"1": "Cute",
"2": "Fine",
"3": "Scary",
},
formatter:"lookup", // display option, but store value
formatterParams:{
"1": "Cute",
"2": "Fine",
"3": "Scary",
}
}

How to update embedded document?

How to update the text of second comment to "new content"
{
name: 'Me',
comments: [{
"author": "Joe S.",
"text": "I'm Thirsty"
},
{
"author": "Adder K.",
"text": "old content"
}]
}
Updating the embedded array basically involves two steps:
1.
You create a modified version of the whole array. There are multiple operations that you can use to modify an array, and they are listed here: http://www.rethinkdb.com/api/#js:document_manipulation-insert_at
In your example, if you know that the document that you want to update is the second element of the array, you would write something like
oldArray.changeAt(1, oldArray.nth(1).merge({text: "new content"}))
to generate the new array. 1 here is the index of the second element, as indexes start with 0. If you do not know the index, you can use the indexesOf function to search for a specific entry in the array. Multiple things are happening here: changeAt replaces an element of the array. Here, the element at index 1 is replaced by the result of oldArray.nth(1).merge({text: "new content"}). In that value, we first pick the element that we want to base our new element from, by using oldArray.nth(1). This gives us the JSON object
{
"author": "Adder K.",
"text": "old content"
}
By using merge, we can replace the text field of this object by the new value.
2.
Now that we can construct the new object, we still have to actually store it in the original row. For this, we use update and just set the "comments" field to the new array. We can access the value of the old array in the row through the ReQL r.row variable. Overall, the query will look as follows:
r.table(...).get(...).update({
comments: r.row('comments').changeAt(1,
r.row('comments').nth(1).merge({text: "new content"}))
}).run(conn, callback)
Daniel's solution is correct. However, there are several open issues on Github for planned enhancements, including:
generic object and array modification (https://github.com/rethinkdb/rethinkdb/issues/895)
being able to specify optional arguments for merge and update (https://github.com/rethinkdb/rethinkdb/issues/872)
being able to specify a conflict resolution function for merge (https://github.com/rethinkdb/rethinkdb/issues/873)
...among other related issues. Until those are introduced into ReQL (particularly #895), Daniel's approach is the correct one.

Resources