Filter only Service and NonInventory type items in QuickBooks item api - quickbooks

In Item API Documentaiton we can see there are different types of Item that we can filter/sort from. And I am only interested in Item.Type = 'NonInventory' OR Item.type = 'Service'.
API query
SELECT * from Item where Active IN (true, false) AND Type IN ('Service', 'NonInventory')
But I only get all items as Service Type. Even NonInventory type item.type is Service. Now how do I determine, which one is Service and which one is NonInventory by checking the Status or any other attribute? Also I want to exclude, Categories and Bundle from the Response.

After passing minor_version = 42 in API endpoint, I am getting correct result, and able to filter Service and NonInventory items only.
Reference: https://developer.intuit.com/app/developer/qbo/docs/develop/explore-the-quickbooks-online-api/minor-versions#minor-version-summary

Related

How can I retrieve all members when querying for appRoleAssignedTo in Microsoft Graph?

I am attempting to programmatically retrieve a list of users (principalType = "User") and their associated appRoleId values for an enterprise app using itsresourceId value from Azure AD. There is a total of ten Users with a combined total of twenty appRoleId values associated with the app. However, when I run my query I receive data for just two users and a combined total of four appRoleId values.
Here's my C# code:
GraphServiceClient myGraphClient = GetGraphServiceClient([scopes]);
// Retrieve the [Id] value for the app. Note [Id] is a pseudonym for the [resourceId] required to retrieve users and app roles assigned.
var servPrinPage = await myGraphClient.ServicePrincipals.Request()
.Select("id,appRoles")
.Filter($"startswith(displayName, 'Display Name')")
.GetAsync()
.ConfigureAwait(false);
// Using the first [Id] value from the [ServicePrincipals] page, retrieve the list of users and their assigned roles for the app.
var appRoleAssignedTo = await myGraphClient.ServicePrincipals[servPrinPage[0].Id].AppRoleAssignedTo.Request().GetAsync().ConfigureAwait(false);
The query returns a ServicePrincipalAppRoleAssignedToCollectionPage (as expected) but the collection only contains four pages (one per User/appRoleId combination).
As an aside, the following query in Microsoft Graph Explorer produces an equivalent result:
https://graph.microsoft.com/v1.0/servicePrincipals/[resourceId]/appRoleAssignedTo
What am I missing here? I need to be able to retrieve the complete list of users and assigned app roles. Any assistance is greatly appreciated.
The issue I was confronting has to do with the pagination feature employed by Azure AD and MS Graph. In a nutshell, I was forced to submit two queries in order to retrieve all twenty records I was expecting.
If you have a larger set of records to be retrieved you may be faced with submitting a much larger number of successive queries. The successive queries are managed using a "skiptoken" passed as a request header each time your query is resubmitted.
Here is my revised code with notation....
// Step #1: Create a class in order to strongly type the <List> which will hold your results.
// Not absolutely necessary but always a good idea when working with <Lists> in C#.
private class AppRoleByUser
{
public string AzureDisplayName;
public string PrincipalDisplayName;
}
// Step #2: Submit a query to acquire the [id] for the Service Principal (i.e. your app).
// Note the [ServicePrincipals].[id] property is synonymous with the [resourceId] needed to
// retrieve [AppRoleAssignedTo] values from Microsoft Graph in the next step.
// Initialize the Microsoft Graph Client.
GraphServiceClient myGraphClient = GetGraphServiceClient("Directory.Read.All");
// Retrieve the Service Principals page containing the app [Id].
var servPrinPage = await myGraphClient.ServicePrincipals.Request().Select("id,appRoles").Filter($"startswith(displayName, 'Your App Name')").GetAsync().ConfigureAwait(false);
// Store the app [Id] in a local variable (for readability).
string resourceId = servPrinPage[0].Id;
// Step #3: Using the [Id]/[ResourceId] value from the previous step, retrieve a list of AppRoleId/DisplayName pairs for your app.
// Results of the successive queries are typed against the class created earlier and are appended to the <List>.
List<AppRoleByUser> appRoleByUser = new List<AppRoleByUser>();
// Note, unlike "Filter" or "Search" parameters, it is not possible to
// add a "Skiptoken" parameter directly to your query in C#.
// Instead, it is necessary to insert the "skiptoken" as request header using the Graph QueryOption class.
// Note the QueryOption List is passed as an empty object on the first pass of the while loop.
var queryOptions = new List<QueryOption>();
// Initialize the variable to hold the anticipated query result.
ServicePrincipalAppRoleAssignedToCollectionPage appRoleAssignedTo = new ServicePrincipalAppRoleAssignedToCollectionPage();
// Note the number of user/role combinations associated with an app is not always known.
// Consequently, you may be faced with the need to acquire multiple pages
// (and submit multiple consecutive queries) in order to obtain a complete
// listing of user/role combinations.
// The "while" loop construct will be utilized to manage query iteration.
// Execution of the "while" loop will be stopped when the "bRepeat" variable is set to false.
bool bRepeat = true;
while (bRepeat == true)
{
appRoleAssignedTo = (ServicePrincipalAppRoleAssignedToCollectionPage) await myGraphClient.ServicePrincipals[resourceId].AppRoleAssignedTo.Request(queryOptions).GetAsync().ConfigureAwait(false);
foreach (AppRoleAssignment myPage in appRoleAssignedTo)
{
// I was not able to find a definitive answer in any of the documents I
// found but it appears the final record in the recordset carries a
// [PrincipalType] = "Group" (all others carry a [PrincipalType] = "User").
if (myPage.PrincipalType != "Group")
{
// Insert "User" data into the List<AppRoleByUser> collection.
appRoleByUser.Add(new AppRoleByUser{ AzureDisplayName = myPage.PrincipalDisplayName, AzureUserRole = myPage.AppRoleId.ToString() });
}
else
{
// The "bRepeat" variable is initially set to true and is set to
// false when the "Group" record is detected thus signaling
// task completion and closing execution of the "while" loop.
bRepeat = false;
}
}
// Acquire the "nextLink" string from the response header.
// The "nextLink" string contains the "skiptoken" string required for the next
// iteration of the query.
string nextLinkValue = appRoleAssignedTo.AdditionalData["#odata.nextLink"].ToString();
// Parse the "skiptoken" value from the response header.
string skipToken = nextLinkValue.Substring(nextLinkValue.IndexOf("=") + 1);
// Include the "skiptoken" as a request header in the next iteration of the query.
queryOptions = new List<QueryOption>()
{
new QueryOption("$skiptoken", skipToken)
};
}
That's a long answer to what should have been a simple question. I am relatively new to Microsoft Graph but it appears to me Microsoft has a long way to go in making this API developer-friendly. All I needed was to know the combination of AppRoles and Users associated with a single, given Azure AD app. One query and one response should have been more than sufficient.
At any rate, I hope my toil might help save time for someone else going forward.
Could you please remove "Filter" from the code and retry the operation. Let us know if that worked.

What's the max possible length of an id list that can be sent to YT video API?

I call YT.Channel API with a list of Ids and I get an error:
GoogleJsonResponseException: API call to youtube.channels.list failed with error: Request contains an invalid argument.
YouTube.Channels.list('id, snippet, statistics', {
id: resultsParentChannelIdsPerPage.join()
}).getItems()
id = UC5JU3rLOMvB7ZIXI2oi1ubg,UC4mKtxAtWQgmkFC6S6siNVg,UC-4hR9ralZoAW15tAwSbJ_A,UCvdwiASqQrIIozQcVAXvRXw,UCUIKx2bIjRcBWyIa3AQGSCg,UClkJAMCknefAzrYfpk1_0Nw,UCsDm3gAWuDRDLMjZLoUxOuA,UC-OkSUXpLrS2eBpztAJ78wg,UCb6RivygioXGs0icq4McBdg,UCmAf6BdYS-5QmXxBuJZgNpQ,UC6rDrJjome8e_iBQI1MLeZg,UCJ0lYZCucWTPc_IfE2vZNTg,UCVy5saLw3psF5laPWhahGHA,UCXskq-my9ltmT6SpdL7b_cw,UCpctmQs9AEwiIZgTcWSV0mg,UCv4ZlVO5-z-uVIm1Y6ol-DA,UCPtQnd-8OBSzvqnQVKaA_8g,UC_uQYR3lHS36jkBRqdvQIFw,UCoJuf64ajKTOZ6mX30zulKg,UCM-GJfgjXFajHll_uGeZPBQ,UC2ojGYd_fg8oU71beXUMW9g,UCT_dVMJ2eSGKugeXnMZcbfQ,UC6PHRps6wOfBJKoDxEI37Ew,UC2Ra3RK4FW38skAoYEtXJbQ,UC2u7_TuItL4on_9SuwJhO_A,UCt-gKqNg_k2bb-bSe7y3z4g,UC2UotqDGeOMUl-gQG3t9sKw,UCdbVBcrKBtu8oUcp4JuLpvw,UCKHpDyswx5VskURci4FPqUA,UCiNHdTU2jYRbUf1cbMCxdaQ,UC3osMa_MdseDVrXlbZFSZDw,UCbnwaC-Tbi1duuDbjfV-Thg,UCBOrTOryVc2JKsNOu7_wO6g,UCM8UoJ4z4NMvp5pwYQjx8uQ,UCnU2sysDk58MuMQHxqgDd7w,UCuldUFBFddgeVN6HJ-yIBjA,UCsEgNI5S2Vdy3Q7LizK2OSA,UClN9w3sTTs6lpntoeHyYvSA,UCgZlOI3AqanZW0tjCSJCKfA,UCqS9WhAUJ-6PiC-8mZ0rDSQ,UCBH5Es0HeCBBlHvWG9c2ipA,UCpPgyVE8TKJr-MnpB44Au4w,UCJxgQl6TU8FGmMzG24xxYFg,UCpe9hHSEkTs5BD6Ufi0-XuA,UCrk1G4da0dsnLsPjsov5fTA,UCtF629dMzswzAupMUEO-bPw,UCsRcjJkUmU_Ny5D9pn5ZGDw,UC5Wm0eXXRAA6Pcjlq8-EaLw,UCOakkksW_nWRDkPl43VzAQA,UC4JhVBsy-Yfr3dQy7G1EYuQ,UCfS8vOYmleKZU8zNjzsZ6qg,UCPWsJzhhZSPlfQ7DOjSA4Fg,UCPKKa8RgdfoMRBkyt8BhIqA,UCa3bfoq50eqErBDgq0p2cQA,UCyH05wKVW-96Lz2mqhGnzVw,UCiXjl5HwqmuCjr5ZmW00csQ,UCA9tlIHeg-k8z3PUpozkUmA,UC_Bc8M2p5fpYqlfWvbVmw2g,UCnD86huZnRWKDMZISbQx6kg,UCtRn5U4Uz2vbREF0qD0TLuA
I didn't get this in previous similar runs. What has changed?
API explorer
Nothing has changed, as far as I know. Fact is that -- with the exception of CommentThreads.list, Comments.list and Members.list endpoints -- all YouTube Data API endpoints that are providing result sets would not return result sets of more than 50 items.
Therefore, when using the Channels.list endpoint's request parameter id, you'll have to limit yourself to pass to it a comma-separated list of channel IDs of at most 50 elements.

Search for an event according to a specific value of a singleValueExtendedProperty

Situation:
We have an old application that is creating events in outlook (via MAPI). To identify the events the custom property 'CTOID' is set with a specific value by which the events can be found again.
For a newer application we would like to use the Graph API but the application should still be able to read/find the events created by the old application. So I created a test event with a specific CTOID and I can already use the graph client to get the mentioned event with the according property and its value (queryOptions is just some start-/enddate restrictions).
// Initialize the GraphServiceClient.
GraphServiceClient client = await m_MicrosoftGraphClient.GetGraphServiceClient();
// Load user events.
var request = client.Users[userId].CalendarView.Request(queryOptions).Expand("singleValueExtendedProperties($filter=id%20eq%20'Double%20{00020329-0000-0000-C000-000000000046}%20Name%20CTOID')");
var result = await request.GetAsync();
var calendarEvents = result.CurrentPage;
Result:
The event gets fetched correctly including the value for the CTOID property.
Problem:
I can "Expand" events so they contain the value for the CTOID property. But how do I find an event with a specific CTOID value? And specifically, how do I do this with the Graph client in C#?
According to the documentation and this Stackoverflow post, the following REST call should work:
GET /users/{id|userPrincipalName}/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq '{id_value}' and ep/value eq '{property_value}')
So I tried this in the online Graph Explorer:
https://graph.microsoft.com/v1.0/users/[MY_USER_ID]/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq 'Double {00020329-0000-0000-C000-000000000046} Name CTOID' and ep/value eq '229236')
But all I get as response is:
{
"error": {
"code": "ErrorInvalidUrlQueryFilter",
"message": "The filter expression for $filter does not match to a single extended property and a value restriction.",
"innerError": {
"date": "2020-08-03T12:44:05",
"request-id": "33e82c77-92ea-4865-a8d0-00cfc2f99154"
}
}
}
What am I doing wrong? I'm out of ideas and any help would be greatly appreciated.
(Also if you have any idea how to do this with the Graph client in C# and not just the bare REST call).
Additional Information:
Don't know if it's important, but the following permissions are set for our application:
In your filter you need to cast the value to a Double eg
https://graph.microsoft.com/v1.0/users/[MY_USER_ID]/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq 'Double {00020329-0000-0000-C000-000000000046} Name CTOID' and cast(ep/value, Edm.Double) eq 229236)
For anything other then a String in a filter you need to do this

VSTS / TFS REST API - Fetch Work Items and their linked ones

I am retrieving some User Stories using the the VSTS / TFS Web API and the code below:
var getWorkItemsHttpRequestMessage = new HttpRequestMessage(new HttpMethod("GET"), uri + "/_apis/wit/workitems?ids=736,731&&api-version=4.1");
var getWorkItemsHttpResponse = client.SendAsync(getWorkItemsHttpRequestMessage).Result;
if (getWorkItemsHttpResponse.IsSuccessStatusCode)
{
var workItems = getWorkItemsHttpResponse.Content.ReadAsAsync<HttpWorkItems>().Result;
// ...
The query returns all the fields of the work items (user stories, in this case), but not the other items that is linked to them.
I would like to retrieve the Tasks related to these User Stories.
How can it be done ?
Is there another better way to do it ?
You can use the $expand parameter in the URL with the value relations:
https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/4?$expand=relations&api-version=4.1
In the results, you will get the work item links in the section relations:
"relations":[
{
"rel":"System.LinkTypes.Hierarchy-Forward",
"url":"https://dev.azure.com/shaykia/_apis/wit/workItems/5",
"attributes":{
"isLocked":false
}
In the example above, we check work item 4 in the API, and in the results, we can see that work item 5 linked to him with a type of System.LinkTypes.Hierarchy-Forward that work item 4 the parent of 5 (5 he is the child, a task in this case).
You can read here about the relations types.

Get meetings by organizer or attendee email ID using GoToMeeting SDK

I am using .Net sdk of GoToMeeting.
I want to get meetings organized by particular organizer.
I have tried using
MeetingsApi.getHistoryMeetings but it does not return me OrganizerKey so I can not filter on particular Organizer.
Is there any way to get meeting(s) based on organizer or even by Attendee email ID by using .Net SDK?
What is the problem you are facing with MeetingsApi.getHistoryMeetings();?
why you need to filter the method, the MeetingsApi.getHistoryMeetings(accessToken,true,date1,date2); itself filtered for a particular user right?
Look on the arguments we are passing in the method?
accessToken - This token is generated as a result of successful authentication of a gotoproduct account. (In API call it can be generated using directlogin orOauth method.
true - this represents whether the meetings returned are past or not.
date1 - Start date range for the meetings.
date2 - End date range for the meetings.
below code is the sample for getting history meetings.
DateTime sdt=DateTime.Parse("07/01/2015");
DateTime edt=DateTime.Parse("07/30/2015");
List<MeetingHistory> historymeets = new System.Collections.Generic.List<MeetingHistory>();
historymeets=meeting.getHistoryMeetings(accesToken, true, sdt, edt);
foreach (var item in historymeets)
{
Console.WriteLine(item.subject);
}
try it out... The above code will store the meetings in historymeets collection object.
You can do the filter function in that collection object.
UPDATE :
List<MeetingHistory> historymeets = new System.Collections.Generic.List<MeetingHistory>();
historymeets=meeting.getHistoryMeetings(accesToken, true, sdt, edt);
List<AttendeeByMeeting> lstAttendee = new System.Collections.Generic.List<AttendeeByMeeting>();
foreach (var item in historymeets)
{
Console.WriteLine(item.meetingId);
lstAttendee=meeting.getAttendeesByMeetings(accesToken, item.meetingId);
foreach (var itemattendee in lstAttendee)
{
Console.WriteLine(itemattendee.attendeeEmail);
}
}
for comment - It is possible, but not directly because there is no api calls, which supports the meeting by attendee . the above code which i have written is for meeting by organizer . Now you have two options,
get the getHistoryMeetings, now you got the meeting details right? , then get the attendees by meeting id using getAttendeesByMeetings(), filter the two different collection objects with join using LINQ. OR
get the meetingdetails and attendees by executing two different fuinction calls, and store it in database or somewhere else, so that you can access it for doing the filter

Resources