Microsoft Graph Team owner not found for group - microsoft-graph-api

I have aproject project in Java. When I run the project I got a error:
Error message: Team owner not found for group
How to fix it?
final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId("xxxx")
.clientSecret("yyyy")
.tenantId("zzzzz")
.build();
List scope = new ArrayList<>();
scope.add("https://graph.microsoft.com/.default");
final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider( scope, clientSecretCredential);
final GraphServiceClient graphClient =
GraphServiceClient
.builder()
.authenticationProvider(tokenCredentialAuthProvider)
.buildClient();
Group group = new Group();
group.description = "Group with designated owner and members2025";
group.displayName = "Operations group2025";
LinkedList groupTypesList = new LinkedList();
group.groupTypes = groupTypesList;
group.mailEnabled = false;
group.mailNickname = "operations2025";
group.securityEnabled = true;
group.additionalDataManager().put(""owners#odata.bind"", new JsonPrimitive("[ "https://graph.microsoft.com/v1.0/directoryObjects/1111"]"));
group.additionalDataManager().put(""members#odata.bind"", new JsonPrimitive("[ "https://graph.microsoft.com/v1.0/directoryObjects/22222"]"));
Team team = new Team();
TeamMemberSettings memberSettings = new TeamMemberSettings();
memberSettings.allowCreateUpdateChannels = true;
team.memberSettings = memberSettings;
TeamMessagingSettings messagingSettings = new TeamMessagingSettings();
messagingSettings.allowUserEditMessages = true;
messagingSettings.allowUserDeleteMessages = true;
team.messagingSettings = messagingSettings;
TeamFunSettings funSettings = new TeamFunSettings();
funSettings.allowGiphy = true;
funSettings.giphyContentRating = GiphyRatingType.STRICT;
team.funSettings = funSettings;
graphClient.groups(graphClient.groups().buildRequest().post(group).id).team()
.buildRequest()
.put(team).id;
Message response:
2021-08-01 03:08:14.334 ERROR 19944 --- [ main] global : CoreHttpProvider[sendRequestInternal] - 396Graph service exception Error code: BadRequest
2021-08-01 03:08:14.336 ERROR 19944 --- [ main] global : CoreHttpProvider[sendRequestInternal] - 396Error message: Team owner not found for group

You need to allow sometime once you create group or teams or adding members so that it can reflect properly, as they need to create the objects in backend, sync properly - based on my testing this is what i notice.

Related

Create team in GraphAPI returns always null

I am using GraphAPI SDK to create a new Team in Microsoft Teams:
var newTeam = new Team()
{
DisplayName = teamName,
Description = teamName,
AdditionalData = new Dictionary<string, object>()
{
{"template#odata.bind", "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"}
},
Members = new TeamMembersCollectionPage()
{
new AadUserConversationMember
{
Roles = new List<String>()
{
"owner"
},
AdditionalData = new Dictionary<string, object>()
{
{"user#odata.bind", $"https://graph.microsoft.com/v1.0/users/{userId}"}
}
}
}
};
var team = await this.graphStableClient.Teams
.Request()
.AddAsync(newTeam);
The problem is that I get always null. According documentation this method returns a 202 response (teamsAsyncOperation), but the AddAsync method from SDK returns a Team object. Is there any way to get the tracking url to check if the team creation has been finished with the SDK?
Documentation and working SDK works different... As they wrote in microsoft-graph-docs/issues/10840, we can only get the teamsAsyncOperation header values if we use HttpRequestMessage as in contoso-airlines-teams-sample. They wrote to the people who asks this problem, look to the joined teams :)) :)
var newTeam = new Team()
{
DisplayName = model.DisplayName,
Description = model.Description,
AdditionalData = new Dictionary<string, object>
{
["template#odata.bind"] = $"{graph.BaseUrl}/teamsTemplates('standard')",
["members"] = owners.ToArray()
}
};
// we cannot use 'await client.Teams.Request().AddAsync(newTeam)'
// as we do NOT get the team ID back (object is always null) :(
BaseRequest request = (BaseRequest)graph.Teams.Request();
request.ContentType = "application/json";
request.Method = "POST";
string location;
using (HttpResponseMessage response = await request.SendRequestAsync(newTeam, CancellationToken.None))
location = response.Headers.Location.ToString();
// looks like: /teams('7070b1fd-1f14-4a06-8617-254724d63cde')/operations('c7c34e52-7ebf-4038-b306-f5af2d9891ac')
// but is documented as: /teams/7070b1fd-1f14-4a06-8617-254724d63cde/operations/c7c34e52-7ebf-4038-b306-f5af2d9891ac
// -> this split supports both of them
string[] locationParts = location.Split(new[] { '\'', '/', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
string teamId = locationParts[1];
string operationId = locationParts[3];
// before querying the first time we must wait some secs, else we get a 404
int delayInMilliseconds = 5_000;
while (true)
{
await Task.Delay(delayInMilliseconds);
// lets see how far the teams creation process is
TeamsAsyncOperation operation = await graph.Teams[teamId].Operations[operationId].Request().GetAsync();
if (operation.Status == TeamsAsyncOperationStatus.Succeeded)
break;
if (operation.Status == TeamsAsyncOperationStatus.Failed)
throw new Exception($"Failed to create team '{newTeam.DisplayName}': {operation.Error.Message} ({operation.Error.Code})");
// according to the docs, we should wait > 30 secs between calls
// https://learn.microsoft.com/en-us/graph/api/resources/teamsasyncoperation?view=graph-rest-1.0
delayInMilliseconds = 30_000;
}
// finally, do something with your team...
I found a solution from another question... Tried and saw that it's working...

TFS workItem.Validate() issue

Here is the case. I wrote a tool to create a task WorkItem (version 12.0.0.0), it can run normally and create TFS task last month. But Today, when I rerun it, it doesn't create TFS task and show error message: The field "Assigned To" contains the value "email address" that is not in the list of supported values.
NetworkCredential credential = new NetworkCredential("user", "password");
TfsConfigurationServer configurationServer = new TfsConfigurationServer(tfsUri, credential);
ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None);
foreach (CatalogNode collectionNode in collectionNodes)
{
Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId);
ReadOnlyCollection<CatalogNode> projectNodes = collectionNode.QueryChildren(new[] { CatalogResourceTypes.TeamProject }, false, CatalogQueryOptions.None);
foreach (CatalogNode projectNode in projectNodes)
{
Console.WriteLine("Team Project: " + projectNode.Resource.DisplayName);
}
WorkItemStore workstore = teamProjectCollection.GetService<WorkItemStore>();
Project project = workstore.Projects["SpecifiedProject"];
WorkItemType itemtype = project.WorkItemTypes["Task"];
WorkItem workItem = new WorkItem(itemtype);
string assignedTo;
assignedTo = String.Format("{0}#***.com", task.User);
workItem.Fields["Assigned to"].Value = assignedTo;
workItem.Fields["Priority"].Value = task.Priority;
workItem.Fields["Area Path"].Value = AREAPATH;
workItem.Fields["Iteration path"].Value = task.IterationPath;
workItem.Title = task.Title;
workItem.Fields["DESCRIPTION"].Value = task.Description;
workItem.Fields["Original Estimate"].Value = task.EstimatedTime.ToString();
workItem.Fields["Completed Work"].Value = task.ActualTime.ToString();
workItem.Fields["Remaining Work"].Value = task.RemainTime.ToString();
// get the link type for hierarchical relationships
var linkType = workstore.WorkItemLinkTypes[CoreLinkTypeReferenceNames.Hierarchy];
//var linkType = workstore.WorkItemLinkTypes[CoreLinkTypeReferenceNames.Dependency];
RelatedLink rl = new RelatedLink(linkType.ReverseEnd, task.UserStoryID);
workItem.Links.Add(rl);
ArrayList ValidationResult = workItem.Validate();
I think this code block "ArrayList ValidationResult = workItem.Validate();" has some issues, for detail error: enter image description here

How to create a Stripe Invoice for a connect account on a shared customer

I have successfully created a customer on my Stripe platform account. Now I want to create an invoice for that customer from one of my connect accounts.
The connect account delivered a service to the customer and now will be invoicing the customer for payment - I am using the Stripe Invoice capability.
However, I am getting the error "No such customer: cus_XXXX" even after following examples to associate the connect account with the customer account.
I have followed https://stripe.com/docs/connect/shared-customers#making-tokens to create a token for my platform customer and then use that token to create a connect account customer as indicated at https://lorenzosfarra.com/2017/09/19/stripe-shared-customers/ but am still getting the same error message.
Even though it seems that the connect account reference is created successfully - as there are no errors returned, the resulting customer ID is not found.
Here is my Create Invoice Method
public static async Task<string> CreateCustomerInvoice(string secretKey, string customerId, TenantBillHeaderModel billHeader)
{
StripeConfiguration.ApiKey = secretKey;
var fees = await Database.GetAdminFees();
var salesTax = await Database.GetCountrySalesTax(13);// Hardcoded for launch
var billLines = await Database.GetTenantBillDetailForHeaderId(billHeader.TenantBillHeaderId);
var stripeContact = await Database.GetStripeContact(UserInfo.Instance.Organisation.OrganisationId);
InvoiceItemCreateOptions invoiceItemOptions = null;
// Find Fee Percentage
var tFee = billHeader.GrossAmount * (fees.FirstOrDefault(f => f.AdminFeeId == (int)Persistence.Enums.AdminFeeEnum.ConnectCut)).Percentage / 100;
// Create token so that customer can be shared with Connect account - See https://stripe.com/docs/connect/shared-customers
var customerTokenId = await CreateCustomerToken(secretKey, customerId, stripeContact.StripeConnectToken);
//Associates customer with connect account so that it is shared with platform account
var connectCustId = await CreateCustomerInConnectAccount(secretKey, customerTokenId, stripeContact.StripeConnectToken);
foreach (var l in billLines)
{
invoiceItemOptions = new InvoiceItemCreateOptions
{
Quantity = l.Quantity,
UnitAmount = Convert.ToInt64(l.Amount * 100), // Converting to cents for Stripe
Currency = "aud", // Hardcoded for launch
CustomerId = connectCustId,
Description = l.Name + " (" + l.Description + ")",
TaxRates = new List<string> {
salesTax.StripeTaxRateId
},
};
var itemService = new InvoiceItemService();
InvoiceItem invoiceItem = await itemService.CreateAsync(invoiceItemOptions);
}
var invoiceOptions = new InvoiceCreateOptions
{
CustomerId = connectCustId,
AutoAdvance = false, // do not auto-finalize this draft after ~1 hour
CollectionMethod = "send_invoice", // Stripe will progress the a send state. However it will not email as this is trurned off in portal https://stripe.com/docs/billing/invoices/customizing
ApplicationFeeAmount = Convert.ToInt64(tFee),
Description = "Invoice for Advizr Bill: " + billHeader.BillNumber,
DueDate = billHeader.DueDate
};
var service = new InvoiceService();
Invoice invoice = await service.CreateAsync(invoiceOptions);
return invoice.Id;
}
Here I create a customer token
public static async Task<string> CreateCustomerToken(string secretKey, string customerId, string stripeContactId)
{
StripeConfiguration.ApiKey = secretKey;
RequestOptions requestOptions = null;
var options = new TokenCreateOptions
{
CustomerId = customerId,
};
if (stripeContactId != null)
{
requestOptions = new RequestOptions
{
StripeAccount = stripeContactId
};
}
var service = new TokenService();
Token token = await service.CreateAsync(options, requestOptions);
return token.Id;
}
and here I create / associate the customer with the connect account
public static async Task<string> CreateCustomerInConnectAccount(string secretKey, string customerToken, string connectAccount)
{
StripeConfiguration.ApiKey = secretKey;
var options = new CustomerCreateOptions
{
Source = customerToken
};
var requestOptions = new RequestOptions
{
StripeAccount = connectAccount
};
var service = new CustomerService();
Customer customer = await service.CreateAsync(options, requestOptions);
return customer.Id;
}
Any guidance on how to create an invoice for a shared customer (Exists in platform account and is associated with the connect account) will be appreciated.
The customer will then pay the invoice and I will use a destination to pay the connect account after deducting the Application Fee.
Thanks
After logging and issue with Stripe Support, they provided me with the answer.
To resolve this issue, the connect Account
var requestOptions = new RequestOptions
{
StripeAccount = stripeContact.StripeConnectToken
};
must be provided when creating an invoice line item
var itemService = new InvoiceItemService();
InvoiceItem invoiceItem = await itemService.CreateAsync(invoiceItemOptions, requestOptions);
and when creating the invoice.
var service = new InvoiceService();
Invoice invoice = await service.CreateAsync(invoiceOptions, requestOptions);
Hope this helps someone.

Fetch latest checked in information using TfvcHttpClient Class

Trying to fetch latest checked in information using TfvcHttpClient class from a specific folder in Team Foundation Server using its client API from a console application.
Please help how can I achieve it? I have personal access token and below mentioned is able to connect by using it:
Code:
string uri = _uri;
string personalAccessToken = _personalAccessToken;
string project = _project;
string credentials = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalAccessToken)));
//create wiql object
var wiql = new
{
query = "Select [State], [Title] " +
"From WorkItems " +
"Where [Work Item Type] = 'Bug' " +
"And [System.TeamProject] = '" + project + "' " +
"And [System.State] <> 'Closed' " +
"Order By [State] Asc, [Changed Date] Desc"
};
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(uri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
//serialize the wiql object into a json string
var postValue = new StringContent(JsonConvert.SerializeObject(wiql), Encoding.UTF8, "application/json"); //mediaType needs to be application/json for a post call
//send query to REST endpoint to return list of id's from query
var method = new HttpMethod("POST");
var httpRequestMessage = new HttpRequestMessage(method, uri + "/_apis/wit/wiql?api-version=2.2") { Content = postValue };
var httpResponseMessage = client.SendAsync(httpRequestMessage).Result;
}
I have tried below mentioned code for achieving:
VssConnection connection = new VssConnection(serverUrl, new
VssBasicCredential(string.Empty, _personalAccessToken));
var buildServer = connection.GetClient<BuildHttpClient>(); // connect to the build server subpart
var sourceControlServer = connection.GetClient<Microsoft.TeamFoundation.SourceControl.WebApi.TfvcHttpClient>(); // connect to the TFS source control subpart
var changesets = buildServer.GetChangesBetweenBuildsAsync("client-rsa", 1, 5).Result;
foreach (var changeset in changesets)
{
var csDetail = sourceControlServer.GetChangesetAsync("client-rsa", Convert.ToInt32(changeset.Id.Replace("C", string.Empty).Trim()), includeDetails: true).Result;
var checkinNote = csDetail.CheckinNotes?.FirstOrDefault(_ => _.Name == "My check-in note");
if (checkinNote != null)
{
Console.WriteLine("{0}: {1}", changeset.Id, changeset.Message);
Console.WriteLine("Check-in note: {0}", checkinNote.Value);
}
else
Console.WriteLine("Warning: {0} has no check-in note", changeset.Id);
}
Here is the simple sample code which use TfvcHttpClient to get the latest changeset information:
string purl = "https://xxx.visualstudio.com";
string projectname = "projectname";
VssCredentials creds = new VssClientCredentials();
creds.Storage = new VssClientCredentialStorage();
VssConnection vc = new VssConnection(new Uri(purl),creds);
TfvcHttpClient thc = vc.GetClient<TfvcHttpClient>();
TfvcChangesetSearchCriteria tcsc = new TfvcChangesetSearchCriteria();
//Specify the server path of the folder
tcsc.ItemPath = "$/XXXX/XXXX";
//Get the entire history of the specified path
List<TfvcChangesetRef> changerefs = thc.GetChangesetsAsync(projectname,null,null,null,null,tcsc).Result;
//Get the latest changeset ref
TfvcChangesetRef changeref = changerefs.First();
//Get the changeset
TfvcChangeset changeset = thc.GetChangesetAsync(projectname,changeref.ChangesetId).Result;
//Get the detailed changes
List<TfvcChange> changes = thc.GetChangesetChangesAsync(changeref.ChangesetId).Result;
foreach (TfvcChange cg in changes)
{
//Code to read detail information
}

With C# Dev Kit, Invoice Not Appearing In QB

The code seems to run. I don't get any error messages, but an invoice does not appear in QB after I sync. The code is basically this (http://pastebin.com/y7QENxeX) with a few (presumably) minor changes as noted. I'm able to create Accounts and Customers so I believe the basic infrastructure of my app is good. I don't understand why I'm stuck on invoices. I think my customerID is 2. I only have 5 in my company right now. And I think my itemID is 1 as I only have one in QB right now.
Any and all help is greatly appreciated.
Intuit.Ipp.Data.Qbd.PhysicalAddress physicalAddress = new Intuit.Ipp.Data.Qbd.PhysicalAddress();
physicalAddress.Line1 = "123 Main St.";
physicalAddress.Line2 = "Apt. 12";
physicalAddress.City = "Mountain View";
physicalAddress.CountrySubDivisionCode = "CA";
physicalAddress.Country = "USA";
physicalAddress.PostalCode = "94043";
physicalAddress.Tag = new string[] { "Billing" };
Intuit.Ipp.Data.Qbd.InvoiceHeader invoiceHeader = new Intuit.Ipp.Data.Qbd.InvoiceHeader();
invoiceHeader.ARAccountId = new Intuit.Ipp.Data.Qbd.IdType() { idDomain = Intuit.Ipp.Data.Qbd.idDomainEnum.QB, Value = "37" };
invoiceHeader.ARAccountName = "Accounts Receivable";
// original code : invoiceHeader.CustomerId = new IdType() { idDomain = idDomainEnum.NG, Value = "3291253" };
invoiceHeader.CustomerId = new Intuit.Ipp.Data.Qbd.IdType() { idDomain = Intuit.Ipp.Data.Qbd.idDomainEnum.QB, Value = "2" };
invoiceHeader.Balance = (decimal)100.00;
invoiceHeader.BillAddr = physicalAddress;
invoiceHeader.BillEmail = "detroit#tigers.com";
invoiceHeader.CustomerName = "Detroit Tigers";
invoiceHeader.DocNumber = "1234567";
invoiceHeader.DueDate = DateTime.Now;
invoiceHeader.ShipAddr = physicalAddress;
invoiceHeader.ShipDate = DateTime.Now;
invoiceHeader.TaxAmt = (decimal)5;
invoiceHeader.TaxRate = (decimal).05;
invoiceHeader.ToBeEmailed = false;
invoiceHeader.TotalAmt = (decimal)105.00;
List<Intuit.Ipp.Data.Qbd.InvoiceLine> listLine = new List<Intuit.Ipp.Data.Qbd.InvoiceLine>();
//Loop for multiple invoice lines could be added here
Intuit.Ipp.Data.Qbd.ItemsChoiceType2[] invoiceItemAttributes = { Intuit.Ipp.Data.Qbd.ItemsChoiceType2.ItemId, Intuit.Ipp.Data.Qbd.ItemsChoiceType2.UnitPrice, Intuit.Ipp.Data.Qbd.ItemsChoiceType2.Qty };
// original code : object[] invoiceItemValues = { new IdType() { idDomain = idDomainEnum.QB, Value = "5" }, new decimal(33), new decimal(2) };
object[] invoiceItemValues = { new Intuit.Ipp.Data.Qbd.IdType() { idDomain = Intuit.Ipp.Data.Qbd.idDomainEnum.QB, Value = "1" }, new decimal(33), new decimal(2) };
var invoiceLine = new Intuit.Ipp.Data.Qbd.InvoiceLine();
invoiceLine.Amount = 66;
invoiceLine.AmountSpecified = true;
invoiceLine.Desc = "test " + DateTime.Now.ToShortDateString();
invoiceLine.ItemsElementName = invoiceItemAttributes;
invoiceLine.Items = invoiceItemValues;
invoiceLine.ServiceDate = DateTime.Now;
invoiceLine.ServiceDateSpecified = true;
listLine.Add(invoiceLine);
Intuit.Ipp.Data.Qbd.Invoice invoice = new Intuit.Ipp.Data.Qbd.Invoice();
invoice.Header = invoiceHeader;
invoice.Line = listLine.ToArray();
Intuit.Ipp.Data.Qbd.Invoice addedInvoice = commonService.Add(invoice);
Chris
You need to read the following information about how QuickBooks for Windows Sync Manager works, how to see if Sync ran correctly, if objects are in an errored state and how to resolve. It could be any number of things. Once a record is inserted into the cloud, it asynchronously downloads to QuickBooks on the desktop, at which time business logic is applied and records are matched from the cloud to the desktop. If there is an issue, sync manager will show a record of the object that failed, why it failed and the object will now be in an error state.
At this point you can review the error and take steps to fix, like revert or update and resubmit. Links to the documentation below.
QuickBooks Sync Manager
Data Sync
Objects in Errored State
Sync Activity
Sync Status
regards
Jarred

Resources