Hi, dear community.
Our team faced with the next issue:
We need to build a custom automation process for Creating a Quote with Quote Lines from the Opportunity form by a custom button on the web form. At the next step on each Quote Line, the functionality of Import from Project Estimation need to be executed.
Solved Steps:
1. Button was successfully created with JavaScript functionality for Quote creation. Placed on form and work as it should. Code below
function createQuote() {
Xrm.Utility.showProgressIndicator("Wait please until Quote creating.");
var opportunityId = Xrm.Page.data.entity.getId().replace('{', '').replace('}', '');
var serverURL = Xrm.Page.context.getClientUrl();
var query = "opportunities(" opportunityId ")/Microsoft.Dynamics.CRM.msdyn_CreateQuoteFromOpportunity";
var req = new XMLHttpRequest();
req.open("POST", serverURL "/api/data/v9.1/" query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (req.status >= 200 && req.status <= 300) {
var data = JSON.parse(this.response);
Xrm.Utility.closeProgressIndicator();
var entityFormOptions = {};
entityFormOptions["entityName"] = "quote";
entityFormOptions["entityId"] = data.quoteid;
importQuoteLineDetails(data.quoteid);
// Open the form.
Xrm.Navigation.openForm(entityFormOptions).then(
function (success) {
console.log(success);
},
function (error) {
console.log(error);
alert(error.message);
});
console.log(data);
} else {
Xrm.Utility.closeProgressIndicator();
var error = JSON.parse(this.response).error;
console.log(error);
alert(error.message);
}
}
};
req.send();
}
As everybody can see we call an Action "msdyn_CreateQuoteFromOpportunity" (Project Service - Create Quote From Opportunity).
2. After form opens we can also find a Project-Based and Product-Based Quote Lines under Quote, automatically created based on Opportunity Lines from parent Opportunity

3. The next point - Import Quote Line Details foreach Quote Line. Can be completed with manual clocking button on Quote Line form

But we have a requirements for automate that step.
ISSUE DESCRIPTION:
For solving the last (3) step from the previous paragraph I created a Workflow with optionally ability to run it on-demand and inserted Custom Workflow Activity for executing Action "msdyn_CreateQuoteLineDetailsFromEstimate" (Project Service - Create Quote Line Details From Estimate), code below:
List quoteLines = service.RetrieveMultiple(quoteLinesQuery).Entities.ToList();
QuoteLines.Set(activityContext, quoteLines.Count);
quoteLines.ForEach(ql =>
{
OrganizationRequest req = new OrganizationRequest("msdyn_CreateQuoteLineDetailsFromEstimate");
req["groupByRole"] = 0;
req["groupByTransactionType"] = 0;
req["groupByTransactionCategory"] = 0;
req["groupByWbsLevel"] = 4;
req["Target"] = new EntityReference("quotedetail", ql.Id);
//execute the request
OrganizationResponse response = service.Execute(req);
});
Workflow description below (Custom Workflow Activity marked with red square):

When I performed Unit Testing it work as it should - Quote Line Description was imported, as shown below:

But when I tried to do the same from executing Workflow manually - it executed, completed successfully, but has no effect. Nothing imported.
Tried few times, - the same.

As an option I also tried to implement the same functionality by JavaScript, code below:
function importQuoteLineDetails(quoteId) {
Xrm.Utility.showProgressIndicator("Wait please until Quote Line Details importing.");
Xrm.WebApi.retrieveMultipleRecords("quotedetail", "?$select=quotedetailid&$filter=producttypecode eq 5 and _quoteid_value eq " quoteId).then(
function success(result) {
for (var i = 0; i < result.entities.length; i ) {
console.log(result.entities[i]);
var parameters = {
"groupByRole": 0,
"groupByTransactionType": 0,
"groupByTransactionCategory": 0,
"groupByWbsLevel": 4
};
var query = "quotedetails(" result.entities[i].quotedetailid ")/Microsoft.Dynamics.CRM.msdyn_CreateQuoteLineDetailsFromEstimate";
console.log(query);
var req = new XMLHttpRequest();
req.open("POST", serverURL "/api/data/v9.1/" query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4 /* complete */) {
req.onreadystatechange = null;
if (req.status >= 200 && req.status <= 300) {
Xrm.Utility.closeProgressIndicator();
var data = JSON.parse(this.response);
console.log(data);
} else {
Xrm.Utility.closeProgressIndicator();
var error = JSON.parse(this.response).error;
console.log(error);
alert(error.message);
}
}
};
req.send(parameters);
}
// perform additional operations on retrieved records
},
function (error) {
console.log(error.message);
// handle error conditions
}
);
}
It executes a long time and then fails.
I will be appreciated for any help and suggestions related to our problem.
Best Regards.