CQ Workflow- Comment not transferring between participant with a process step in between - workflow

When there is a process step between two participant steps, the comments is not passing between participants. My Workflow is like this-
ParticipantA ---> Process step X (ecma script) ----> Process step Y (ecma script) -----> ParticipantB
When I add some comment at ParticipantA step it does not carry forward to ParticipantB. Seems OOB functionality has limitations on this.
As a workaround, I am trying to get it at "Process step X" and passing on to Process step Y. I am able to get it but not able to set it for next step.
Below is my code-
log.info("Noop process called for: " + workItem.getWorkflowData().getPayload());
var comment = workItem.getMetaDataMap().get("comment");
log.info("Comment in approval process-----------" + comment);
var workflowData = workItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") {
log.info("setting comment in meta data----------------");
workflowData.getMetaDataMap().put("comment", comment);
}
Can you help on how to set comment for next step?
Thanks in advance.
Regards,
Vivek

You would need to actually store your comment within a workflow Metadata Map. This
should help.
Once you have successfully stored your comment, you can access it later.
Hope this helps

I guess it is a session change within the workflow. The WorkflowData instance will be newly set. You can easily check it in the debugger of your ide. You have to iterate over the HistoryItems as illustrated here:
final List<HistoryItem> history = workflowSession.getHistory(workItem.getWorkflow());
final List<String> comments = new ArrayList<>();
if (history.size() > 0) {
HistoryItem current = history.get(history.size() - 1);
do {
comments.add(current.getComment());
current = current.getPreviousHistoryItem();
} while (current != null);
}
Comments are empty strings, if not set - if i'm not mistaken.

Related

My google sheets function does the job when run from editor but gives different outcome when trigered by Form submit

I have a google form and a sheet that collects the responses which of course always appear at the bottom. I have been using the following script to copy the last response (which is always on the last row) from the Response sheet (Form Responses 2) to row two of another sheet (All Responses). When run by a trigger on Form Submit the script inserts a blank row into All Responses, then the copied values into another row above the blank row. Please can you help and tell me why and how I might change the script so the blank row is not added:
function CopyLastrowformresponse () {
var ss = SpreadsheetApp.getActive();
var AR = ss.getSheetByName("All Responses");
var FR = ss.getSheetByName("Form responses 2");
var FRlastrow = FR.getLastRow();
AR.insertRowBefore(2);
FR.getRange(FRlastrow, 1, FRlastrow, 22).copyTo(AR.getRange("A2"), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}
A few things could be going on here.
You're getting a number of rows equal to FRlastrow, when I think you only want to be getting 1 row.
Apps Script has buggy behavior with onFormSubmit() triggers, so you may to check duplicate triggers (see this answer).
The script isn't fully exploiting the event object provided by onFormSubmit(). Specifically, rather than getting the last row from one sheet, you could use e.values, which is the same data.
I would change the script to be something like this:
function CopyLastrowformresponse (e) {
if (e.values && e.values[1] != "") { // assuming e.values[1] (the first question) is required
SpreadsheetApp.getActive()
.getSheetByName("All Responses")
.insertRowBefore(2)
.getRange(2, 1, 1, e.values.length)
.setValues([e.values]);
}
}
But, ultimately, if all you want to do is simply reverse the order of the results, then I'd ditch Apps Script altogether and just use the =SORT() function.
=SORT('Form responses 2'!A:V, 'Form responses 2'!A:A, FALSE)

mini filter driver | passing information from pre-operation to post-operation

I'm tracking changed made to file and would like to "remember" and pass some information from the pre-operation callback to the post-operation callback.
What is the best way to do it?
[Edit: The driver should only support Windows 10 everything else is a bonus]
You can simply use the PVOID *CompletionContext in PreOperation to store a pointer to the data you want to pass to the PostOperation.
In the PostOperation just use CompletionContext as it will be the data you pointed it to in the PreOperation.
For example:
PreOp:
MyPreOpData = ExAllocatePoolWithTag(DATA_SIZE);
FltGetFileNameInformation(&NameInfo);
MyPreData->NameInfo = NameInfo;
MyPreData->OtherData = MyDrvGetOtherData(Params);
*CompletionContext = MyPreData;
PostOp:
if (CompletionContext != NULL)
{
PMY_DATA MyPreData = (PMY_DATA)CompletionContext;
// now continue using the data queried in the PreOp
...
// when done free it
ExFreePoolWithTag(MyPreData);
}
See here for more details.
Good luck,
Gabriel

Is there a REST endpoint to get a list of a project's task assignments in Project Server?

I've tried sending a request to
"/_api/ProjectServer/Projects('projectid')/Assignments", but all it does is return duplicates of the last assignment which is weird because the number of objects it returns is always equal to the number of assignments there are in the project.
Basically if I assign a resource to each of a hundred different tasks, the call returns 100 duplicates of the last task's assignment in the list.
I suspect it might be a bug, I'd appreciate it if someone could confirm or deny my assumption and/or let me know if there's any other way to retrieve the list of assignments in a project.
I didn't exactly know how to work with rest but I would like to provide you with litle lines of code using CSOM that, if I understood properly the question, it might help you:
private static void ListPublishedProjects()
{
// Get the list of projects on the server.
projContext.Load(projContext.Projects);
projContext.ExecuteQuery();
var proj = projContext.Projects.First(p => p.Name == "<project name>");
projContext.ExecuteQuery();
//You must ckeck out the project and load it's tasks
var draftProj = proj.CheckOut();
projContext.Load(draftProj.Tasks);
projContext.ExecuteQuery();
//Loop between all tasks
foreach (DraftTask task in draftProj.Tasks)
{
// Load all assignments in that task
projContext.Load(task.Assignments);
projContext.ExecuteQuery();
//Loop between al assignments
foreach (var assignment in task.Assignments)
{
projContext.Load(assignment.Owner, temp => temp.LoginName, temp => temp.Email);
projContext.Load(assignment.Resource);
projContext.ExecuteQuery();
Console.WriteLine("\n\t RESOURCE NAME:" + assignment.Resource.Name + " => " + assignment.ActualWork);
}
}
//Remember to publish and checkin the project when you finish your TODOs
draftProj.Publish(true);
draftProj.CheckIn(true);
QueueJob qJob = projContext.Projects.Update();
JobState jobState = projContext.WaitForQueue(qJob, 200);
}
}
Hope it helps,

Add trigger to form

I have been working on a simple "Time off request" form using Google Apps. The I have associated a script with the form which detects the respondents' supervisor and sends them a link to a new form for their approval.
Here is the code from the script I used to create the new form.
//create approval form as part of the Message Creation process.
var approvalForm = FormApp.create("Approve Days off Request")
approvalForm.setTitle("Approval form for " + user.Name)
// truncated ...
var approvalItem = approvalForm.addMultipleChoiceItem(); //Item on First Page
var disapproveReasonPage = approvalForm.addPageBreakItem(); //Page Break Item
var disapproveReason = approvalForm.addParagraphTextItem(); //Item on Second Page
// truncated ...
//Question 1, Page 1
approvalItem.setTitle(user.Name + " has requested " + daysOff + " day(s) off starting on " + firstDate+".")
approvalItem.setHelpText("Would you like to approve this request?")
approvalItem.setRequired(true);
approvalItem.setChoices ([
approvalItem.createChoice('Yes', FormApp.PageNavigationType.SUBMIT),
approvalItem.createChoice('No', FormApp.PageNavigationType.CONTINUE)
]);
//Question 2, Page 2
disapproveReason.setTitle("Would you like to give a reason?");
disapproveReason.setHelpText("Optional")
disapproveReasonPage.setGoToPage(FormApp.PageNavigationType.SUBMIT)
Then a link is generated and sent to the supervisor to approve the request.
I am wanting to add a trigger to the form created above (approvalForm). I would imagine that there is a way, but haven't been able to find the greatest documentation on it. The closest I've come is TriggerBuilder Class. I tried creating one associated to the target form with
var approveScript = ScriptApp.newTrigger('Approval')
.forForm(approvalForm.getId())
.onFormSubmit()
.create();
but couldn't get it to work the way I wanted it. I did have a function named Approval just to see if I could manipulate the form with it
function Approval(){
$form.setAcceptingResponses(false);
}
Any help would be appreciated. Thanks in advance.
The script was originally being added as a container bound script. Changing it to a Standalone installable script fixed this problem. Hopefully this answer will be to someone else having a similar issue.

Trigger works but test doesn't cover 75% of the code

I have a trigger which works in the sandbox. The workflow checks the field in the campaign level and compares it with the custom setting. If it matches, then it returns the target to the DS Multiplier field. The trigger looks as follows
trigger PopulateTarget on Campaign (before insert, before update)
{
for(Campaign campaign : Trigger.new)
{
if (String.isNotBlank(campaign.Apex_Calculator__c) == true)
{
DSTargets__c targetInstance = DSTargets__c.getInstance(campaign.Apex_Calculator__c);
{
String target = targetInstance .Target__c;
campaign.DS_Target_Multiplier__c = Target;
}
}
}
}
However, I had problems to write a proper test to this and asked for the help on the internet. I received the test
#isTest
private class testPopulateTarget{
static testMethod void testMethod1(){
// Load the Custom Settings
DSTargets__c testSetting = new DSTargets__c(Name='Africa - 10 Weeks; CW 10',Target__c='0.1538', SetupOwnerId = apexCalculatorUserId);
insert testSetting;
// Create Campaign. Since it would execute trigger, put it in start and stoptests
Test.startTest();
Campaign testCamp = new Campaign();
// populate all reqd. fields.
testCamp.Name = 'test DS campaign';
testCamp.RecordTypeId = '012200000001b3v';
testCamp.Started_Campaign_weeks_before_Event__c = '12 Weeks';
testCamp.ParentId= '701g0000000EZRk';
insert testCamp;
Test.stopTest();
testCamp = [Select ID,Apex_Calculator__c,DS_Target_Multiplier__c from Campaign where Id = :testCamp.Id];
system.assertEquals(testCamp.DS_Target_Multiplier__c,testSetting.Target__c);// assert that target is populated right
}
}
Such test returns the error "Compile Error: Variable does not exist: apexCalculatorUserId at line 6 column 122". If I remove that ApexCalculator part System.assertEquals then the test passes. However it covers 4/6 part of the code (which is 66%)
Could anyone help me how should I amend the code to make the coverage of 75%?
Yes, apexCalculatorUserId has not been defined. The code you were given appears to be incomplete. You'll need to look at the constructor DSTargets__c and see what kind of ID it is expecting there.
At a guess, you could try UserInfo.getUserId() to get the ID of the current user, but that may not be the ID that's expected in the constructor. It would be worth trying it to see if the test coverage improves.
1) Replace apexCalculatorUserId with UserInfo.getUserId()
2) I'm not sure what kind of field is Apex_Calculator__c on campaign. If its not a formula you want to insert a new line before "insert testCamp". Something like:
testCamp.Apex_Calculator__c = UserInfo.getUserId();