"A Currency is Required if a Value Exists in a Money Field" - Default Currency Is Set - javascript

I'm having a serious issue with one of my managed solutions, I have a custom workflow which creates a bunch of custom entities and these custom entites have several money fields on them.
Here's what happens when I run my workflow:
Custom workflow goes into 'waiting' state and throwns a null reference exception.
Several entities have been created, but one of them has null vlaues in the money fields (they default onLoad to £0.00).
When I open this record, I get the error message mentioned in the tite of this post.
A few things you should know:
The default currency is set in the system (to Pound Sterling).
I have tried to following JavaScript in the OnLoad() event of my form as has been suggested elsewhere on the web:
var lookupData = new Array();
var lookupItem= new Object();
lookupItem.id = "{7bCA916E76-FA28-E211-8C7C-0800273EE9D1}";
lookupItem.entityType = "transactioncurrency";
lookupItem.name = "Pound Sterling";
lookupData[0] = lookupItem;
Xrm.Page.getAttribute("transactioncurrencyid").setValue(lookupData);
If this JS is on thje form and I attempt to create a new record I get the error:
Error: 'Xrm.Page.getAttribute(..)' is null or not an object
Can anyone advise as to what it is I have to do here?
This error only occurs on the live system, not in the development environment.

That's because the ID of the currency you are trying to set is different in the live environment than in the dev environment.
You need to get the ID of the "Pound Sterling" currency from the Live environment and put it where "insert here":
lookupItem.id = "--insert here--";
lookupItem.entityType = "transactioncurrency";
lookupItem.name = "Pound Sterling";
Then it will work.

Related

Troubleshooting SuiteScript 1.0 Line Level Field Sourcing Code (List/Record)

I am an inexperience technical developer working on my first SuiteScript using SuiteScript 1.0. I am getting an SSS_MISSING_REQD_ARGUMENT error, but I am sure there are many more in my code. The purpose of the script is to populate the department field on the expense record line item from a joined record. The end user will select a Project on the expense line, and the script should look up the department on the project record (a custom field) and add the value to the native department field. Code is copied below.
function ProjectSegment ()
{
var record = nlapiLoadRecord(nlapiGetRecordType(), nlapiGetRecordId());
var recordID = nlapiGetRecordId(record);
//internal ID of project record
var project = nlapiGetField ('custcol_nra_expense_project');
//load project record
var precord = nlapiLoadRecord('job', project);
//get department on project record (internal ID)
var pdepartment = precord.GetFieldValue('custentity_nra_dept_project');
//get project name from project record
var projectName = precord.GetFieldText('entityid');
//load existing search
var search = nlapiLoadSearch('job','customsearch161');
//add filter to include project name
search.addFilter(new nlobjSearchFilter('entityid',null,'is',projectName));
//run search
var resultSet = search.runSearch();
//get department line
var departmentResult = new nlobjSearchColumn('custentity_nra_dept_project');
//set value
nlapiSetFieldTexts('job','department',1,departmentResult)
//record.commitLineItem('department');
nlapiSubmitRecord(record, true);
}
//internal ID of project record
var project = nlapiGetFieldValue ('custcol_nra_expense_project');
Praveen Kumar's response is correct regarding the missing required argument, but there are many other issues with the script as you've surmised.
Side notes:
The getFieldValue and getFieldText methods of nlobjRecord are not capitalized.
For performance reasons, you could/should use a search to get the values you need from the job record. Loading a record just to get field values is wasteful unless you mean to change the record.
Your search filter should probably be based on the value (not text) of the entityid in the job record.
Your desired search column probably is invalid (I don't think a custentity field could be on a job record).
Getting the search result is incorrect.
You want something like this instead:
var result = resultSet.getResults(0, 1);
if (result) {
var department = result.getValue('custentity_nra_dept_project');
// etc.
}
All that said, though, from your description, I don't think you need the search anyway. Once you have pdepartment (again, using precord.getFieldValue), I think all you need is:
record.setFieldValue('department', pdepartment);
Or if you're setting the line-level department, it would be different.
What kind of script is this? I'd like to make more recommendations, but it depends on what's going on.

Get all user properties from Microsoft graph

We have an application which has used a local AD to fetch user info. Some customers want to move to the cloud and are using Azure AD. We extended the app to sign users in via owin and now we're fetching users via Microsoft Graph.
However from Microsoft Graph we do not get full user profiles. We want to fetch all properties on users, not just the basic ones.
var client = new RestClient(string.Format("https://graph.microsoft.com/v1.0/users/{0}", userEmail));
request = new RestRequest();
request.Method = Method.GET;
request.AddHeader("Authorization", _token.Token);
var reponse = client.Execute(request);
This only gives me some information though, for example I don't get 'Department' from this.
Is it possible to configure in azure what should be returned here, if so then where? Or do I need something other than /users/?
Different customers might have different special properties that need to be fetched. So the best solution would be to have an endpoint to call and get everything, including special properties not standard in azure ad. After that I can parse it on my side. Is this possible?
The app has permission to read both basic and full profiles. Do I need something more?
That's the normal behaviour of Graph API, see documentation here and this extract:
By default, only a limited set of properties are returned (
businessPhones, displayName, givenName, id, jobTitle, mail,
mobilePhone, officeLocation, preferredLanguage, surname,
userPrincipalName).
To return an alternative property set, you must specify the desired
set of user properties using the OData $select query parameter. For
example, to return displayName, givenName, and postalCode, you would
use the add the following to your query
$select=displayName,givenName,postalCode
You have to specify all fields in the select, as $select=* will only output the key fields in Graph API implementation.
So you will not be able to get what you ask (variable custom fields).
More info on the fields of User can be found here
User user = await graphServiceClient
.Users[emailId]
.Request()
.Select(aadUser => new
{
aadUser.Id,
aadUser.UserPrincipalName,
aadUser.DisplayName,
aadUser.GivenName,
aadUser.Surname,
aadUser.City,
aadUser.MailNickname,
aadUser.UserType
})
.GetAsync()
.ConfigureAwait(false);
As already stated by NicolasR, you must list all the fields you want to retrieve by using the "$select" parameter; if you want, instead, to retrieve the custom fields, you can either add them to the previous parameter (if you know their names) or you can use "$expand=extensions"
function getGraphDataAdvanced($authToken, $urlGraph){
$url = $urlGraph + '&$count=true'
$data = (Invoke-RestMethod -Headers #{
Authorization = "Bearer $($authToken)"
ConsistencyLevel = "eventual"
} -Uri $url -Method Get)
$dataList = #()
$dataList += $data.value
$url = $data.'#Odata.NextLink'
while ($null -ne $url){
Write-Warning 'Retreiving Next Page'
$data = (Invoke-RestMethod -Headers #{
Authorization = "Bearer $($authToken)"
ConsistencyLevel = "eventual"
} -Uri $url -Method Get)
$dataList += $data.value
$url = $data.'#Odata.NextLink'
}
return $dataList
}
getGraphDataAdvanced $authToken 'https://graph.microsoft.com/beta/users? $expand=extensions'
Using the Microsoft Graph Explorer, I've been able to find all available properties for a user:
Go to "Groups"
Select "list all groups in my organization"
Change the query to filter by a group you know and expand members: https://graph.microsoft.com/v1.0/groups?$filter=mail eq 'aGroup#company.com'&$expand=members
Now you'll see all the available properties for the users.
I've been trying to find a way to get all Azure AD properties of objects via Powershell MSGraph cmdlets without it truncating at the right edge of the console.
I've discovered that Format-Custom triggers vomiting of (apparently) all properties of an object in a huge, alphabetical, indented, and bracketed list.
Get-MgUser -filter "startswith(userprincipalname, 'username')" | format-custom
The formatted properties of a newly created and unused user account in Azure AD is 13217 lines long.

'An undeclared property' when trying to create record via Web API

I am getting an error which I just cannot seem to debug. I am trying to create a custom activity entity via custom HTML/JavaScript web resource.
The user clicks a button and the following params:
var params = {
'rob_faqid#odata.bind': '/rob_faqs(guid-here)',
'rob_source': 180840000,
'subject': 'Signpost',
'actualstart': new Date(),
'actualend': new Date()
};
Are passed to this URL:
https://dynamicsorg/api/data/v8.2/rob_quickactions/
With the following headers:
xhr.setRequestHeader('OData-MaxVersion', '4.0');
xhr.setRequestHeader('OData-Version', '4.0');
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.setRequestHeader('Prefer', 'return=representation');
This gives me a HTTP code of 400 (bad request) and this error message:
An undeclared property 'rob_faqid' which only has property annotations in the payload but no property value was found in the payload. In OData, only declared navigation properties and declared named streams can be represented as properties without values.
Interestingly, I get this error whether I use an actual GUID or if I put some gibberish in there (suggesting it is not to do with the value being passed in).
I can create the records manually via the standard form.
I am using the odata.bind elsewhere within the same project with no errors.
After a good night's sleep I realised my error. To set the value of a lookup field, you need to use the relationship scheme name, and not the property name.
Once I changed that, all worked fine.
When you want to set the value of a lookup field during the creation or update of a (new) record via the web API, you have to use either the Schema Name or the Logical Name of the lookup followed by the bind annotation.
For default fields like primarycontactid the logical name has to be used (first column in the screenshot).
For custom fields like rob_FaqId the schema name has to be used (second column in the screenshot).
var params = {
'rob_FaqId#odata.bind': '/rob_faqs(guid-here)',
'rob_source': 180840000,
'subject': 'Signpost',
'actualstart': new Date(),
'actualend': new Date()
};
Screenshot of a solution > entities > your entity > fields:
So the general structure to create a new record with an already set lookup field via the web API is this:
{
"logicalorschemaName#odata.bind": "/relatedentitys(guid)" //don't forget the plural 's'
}
Or another example from the official documentation. How to create a new account record and directly assign an already existing contact as the primary contact.
var newAccountRecordObj = {
"name": "Sample Account",
"primarycontactid#odata.bind": "/contacts(00000000-0000-0000-0000-000000000001)"
}
While the accepted answer is correct in this instance, it doesn't seem to be the whole story. In some cases it's necessary to use <logical name>_<entity name>. For instance when doing a POST sharepointdocumentlocations, I had to use:
"regardingobjectid_contact#odata.bind": "/contacts(xxxx)"
"parentsiteorlocation_sharepointdocumentlocation#odata.bind" "/sharepointdocumentlocations(xxx)"
This may be something to do with the fact that those relationships can point to more than one type of entity, but I haven't found any Microsoft documentation about it.

SAPUI5 Create OData entity with dates - generates incorrect request payload that ends in CX_SXML_PARSE_ERROR

We are trying to create an entity that has date attributes via an odata service. Backend is an sap system. This entity has only 3 key attributes plus a bunch of other attributes. We have identified that dates in the keys are the root cause of the problem.
Keys:
Pernr type string,
begda type datetime
endda type datetime.
The code below, (which does not work), has been severely simplified when trying to troubleshoot the issue. At the moment, it reads an entity from an entity set and immediately tries to create one with exactly the same data.
Code:
var oODataModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/Z_PERSONAL_DATA_SRV/");
//Test entity to be saved
var entity = null;
//Handler for read error
var handleReadE = function (oEvent){
alert("error");
};
//Handler for read success
var handleRead = function (oEvent){
//Get the data read from backend
entity = oEvent.results[0];
//Try to create a new entity with same data
oODataModel.create('/PersDataSet', entity, null, function(){
alert("Create successful");
},function(oError){
alert("Create failed", oError);
});
};
oODataModel.read("/PersDataSet", null, [], true, handleRead, handleReadE);
In the gateway error log, an xml parsing error appears. In this log, we can see the request data and it can be seen that the dates are transported with String types. These dates are defined in the service as DateTimes so the request is rejected.
Example:
<m:properties>
<d:Pernr m:type="Edm.String">00000001</d:Pernr>
<d:Endda m:type="Edm.String">9999-12-31T00:00:00</d:Endda>
<d:Begda m:type="Edm.String">1979-05-23T00:00:00</d:Begda>
When the entity is read, the backend does not send any type information. It sends like the following example:
<m:properties>
<d:Pernr>72010459</d:Pernr>
<d:Endda>9999-12-31T00:00:00</d:Endda>
<d:Begda>1876-07-21T00:00:00</d:Begda>
And, indeed, if we try to save the same info without the type=".." it works. So the problem are the incorrect types ODataModel.create adds to the xml.
My question is:
Can I tell ODataModel.create to not add this type info? It is not doing a good job inferring the types.
Can anyone share an example reading and writing dates through odata?
Thank you very much in advance.
the data returned from oODataModel.read is raw, before you post you need to parse it
var handleRead = function (oEvent){
//Get the data read from backend
entity = oEvent.results[0];
var newEntity = jQuery.extend({},entity);
delete newEntity.__metadata;
newEntity.Begda = new Date(entity.Begda);
newEntity.Endda = new Date(entity.Endda);
//Try to create a new entity with same data
oODataModel.create('/PersDataSet', newEntity, null, function(){
why not use json instead of xml?
Thanks all for the help.
We got this working accounting for the following:
The problem of the wrong types appended to the attributes comes from the read itself. The object returned by read has a __metadata attribute which describes the values. In this object the dates are set with type=edm.string, even when the service says they are DateTime. To me this is a bug of the .read function.
When trying to use the same object to save, create sees the __metatada on the entry and uses those values, producing type edm.string type for the dates. This caused the request to be rejected. Manually changing these __metadata.properties...type to Edm.DateTime makes it work.
In the end, we did the following:
Dates are parsed manually from the Odata response, creating a js Date
object from the strings in format "yyyy-mm-ddT00:00:00", to make it work with control bindings. When we want to save, the reverse is done.
The object to be created is a new object with
only the attributes we care (no __metadata)

Databinding to Windows 8 ListView

I'm having massive problems with databinding to a ListView in a Windows 8 app using Javascript.
Inside the "activated" event on default.js I have written some code to get some data from a web service and push it into an array. This bit works OK and the array is populated.
The problem I have is that the app won't recognise the data. I have this code in a page called inspections.html:
data-win-options="{itemTemplate: select('#imageTextListCollectionTemplate'),
itemDataSource: dataList.dataSource,
layout: {type: WinJS.UI.ListLayout}}
and then in the "activated" event I declare:
var dataList = new Array();
and push the data from the web service into this array. But at runtime I get an error that says something along the lines of "can't find dataSource on undefined dataList".
I've done some of the examples on the MS website and in one of them it creates a dummy dataset and references it from a namespace. I kinda think that what I'm missing here is a namespace too but I don't know what the namespace for default.js is. Or maybe I'm wrong and it's something totally different.
Please help - this is so fundamental (and should be easy) but I can't get my head around it.
Do you want to create datalist in HTML or javascript?
It seems you want to create it from JavaScript. Assuming that you have already pushed your data into array from your webservice, you only need to call:
var dataList = new WinJS.Binding.List(array);
now accessing dataList.dataSource is perfectly valid.
Also, to create the datalist you don't always need an array. You could probably start with an empty list and then keep inserting data directly into the data list from web services, like:
var dataList = new WinJS.Binding.List([]);
dataList.push(value1);
dataList.push(value2);
...
Hope it helps. Let me know if you have any more questions.
If you are getting troubled by assigning datasource in HTML side
Prefer js side like
var list = new WinJS.Binding.List(array here);
listView.itemDataSource = list.dataSource;
by using this you can easily go through the data which you are binding to ListView.

Categories

Resources