I have a scheduled script that does two things. I have checkbox parameters to determine if those things are require on this run of the script. The first time around both are defaulted to true.
function execute(scriptContext) {
var script = runtime.getCurrentScript();
doTask1 = script.getParameter({name: "custscript_tmh_do_task1"});
doTask2 = script.getParameter({name: "custscript_tmh_do_task2"});
if(doTask1){
//Do something
}
if(doTask2){
//Do something
}
//Determine if task1 or task2 needs to happen and set them to true or false.
//Reschedule script if required
if(doTask1 || doTask2){
var scheduledScriptTask = task.create({
taskType: task.TaskType.SCHEDULED_SCRIPT
});
scheduledScriptTask.scriptId = runtime.getCurrentScript().id;
scheduledScriptTask.deploymentId = runtime.getCurrentScript().deploymentId;
scheduledScriptTask.params = {'custscript_tmh_do_task1': doTask1 ,
'custscript_tmh_do_task2': doTask2 };
return scheduledScriptTask.submit();
}
}
The problem is the second time around, it is not doing the tasks when the booleans are set to true. It just skips over them. I have used the debugger to confirm at the point of rescheduling the script the booleans are true.
Question: How do I reschedule a scheduled script with setting a boolean value.
Side Question" I have the parameters created as a script parameter. Is it possible to do this without setting the script parameters in NetSuite?
that's not the correct constructor for generating the task. I always use:
var scheduledScriptTask = task.create({
taskType: task.TaskType.SCHEDULED_SCRIPT,
scriptId: runtime.getCurrentScript().id,
deploymentId: runtime.getCurrentScript().deploymentId,
params: {'custscript_tmh_do_task1': doTask1 ,
'custscript_tmh_do_task2': doTask2 }
});
Also script parameters are passed as strings so you need to convert.
either:
doTask1 = 'T' == script.getParameter({name: "custscript_tmh_do_task1"});
or
doTask1 = script.getParameter({name: "custscript_tmh_do_task1"});
...
if('T' == doTask1){ ...
Checking when you use them ('T' == doTask1) lets you just round trip the string values into your next iteration. If you use them as booleans so you can decide whether the next iteration needs to do both tasks then you'll need to turn them back to strings when you pass them to the next iteration: custscript_tmh_do_task1 : doTask1 ? 'T' : 'F'
You do not need to give the parameters default values in order to pass them on to the next iteration. And any values you give in the task.create method will override the configured values.
Related
This is in reference to this question. I checked our test interface and we are only passing the V93k primary params to the test_suites.add method.
V93K_PRIMARIES = [:lev_equ_set, :lev_spec_set, :timset, :tim_equ_set, :tim_spec_set, :seqlbl, :levset]
primary_tm_params = {}.tap do |primary_hash|
V93K_PRIMARIES.each do |param|
primary_hash[param] = tm_params.delete(param) unless tm_params[param].nil?
end
end
# Create the test suite
t = test_suites.add(test_name, primary_tm_params)
t.test_method = test_methods.amd93k.send(options[:tm].to_sym, tm_params)
V93K_PRIMARIES.each do |primary|
t.send("#{primary}=", primary_tm_params[primary]) unless primary_tm_params[primary].nil?
end
# Insert the test into the flow
test(t, tm_params)
When I set a breakpoint, I do see they were missing. Here they are after updating the code:
:ip=>:L2,
:testmode=>:speed,
:cond=>:pmax,
:if_failed=>:cpu_pmin,
:testtype=>:cpu,
:test_ip=>:bist,
:tm=>"Bist"}
And here is the .tf file generated from the original two tests in the original question:
run_and_branch(cpu_L2_speed_pmin_965EA18)
then
{
}
else
{
#CPU_PMIN_965EA18_FAILED = 1;
}
if #CPU_PMIN_965EA18_FAILED == 1 then
{
run(cpu_L2_speed_pmax_965EA18);
}
else
{
}
I think we have it figured out, thx very much!
The normal approach to this is just to pass everything to flow.test, rather than a subset of the options passed from the flow.
It will only act on the options it recognizes, which are basically the flow control parameters (:id, :if_failed, :unless_enabled, etc) and the test and bin number parameters, and it will just ignore the rest.
Im sending user information to user when he signs in.
var userstuff00 = findSub(user['id']);
userstuff00.then(function(sub){
for(var i in sub){
var userstuff01 = findSub(sub[i.toString()]['id']);
userstuff01.then(function(sub2){
for(var i2 in sub2){
//here i is the last object in sub but i2 is for the first i
console.log(sub[i.toString()]);
console.log(sub2[i2.toString()]);
}
});
}
});
and this is findSub function where usercollection is mongodb table:
function findSub(stuffCode){
var tempMembers = usercollection.find({'stuff ': stuffCode});
return tempMembers;
}
this is user object :
user{
id,
name,
stuff,
subMember[] //list of users where their stuff equals to this users id
}
I want to add every sub2 in that users subMember but i's id is not equal to i2's stuff( I cant add i2 in another i's submember).
how can get submembers for the first i and then find submembers for the second i?
my goal is a list of users that has users as submembers and these users(submembers level 1) have submembers(submembers level 2) and so on (up to level 10) :
Family Tree
This is a typical issue when working with asynchronous code: the synchronous code will finish before any of the asynchronous code. So this loop:
for(var i in sub)
... will finish before any of the then callbacks inside it will be executed. So by the time one of those gets executed, the value of i is already the length of sub.
To be able to use the value of the i at the time you called then (not its callback), there are different solutions. One of them is to use let i instead of var i as it will define a different variable on each iteration of the for loop. Or you can bind the value of i as argument to the then callback:
userstuff01.then(function(i, sub2){
// ^^^ added parameter
for(var i2 in sub2){
//here i is the last object in sub but i2 is for the first i
console.log(sub[i.toString()]);
console.log(sub2[i2.toString()]);
}
}.bind(null, i));
// ^^^^^^^^^^^ bind the parameter value to the current value of i.
I have the following action:
act = SCons.Action.Action('$ACTIONVAR', 'Executing a dummy action')
env['EXTENSION'] = '.err'
env['ACTIONVAR'] = '${SOURCE.filebase}$EXTENSION'
I want to have the value of action var depending on different target and sources.
What I want to achieve could be similar to this:
obj = env.Execute(act('file.o', 'file.c'))
print 'Str: ' + str(obj) #this should print 'file.err'
Is it possible to get the value without executing the action ?
You are searching for the env.subst() method. Please check the MAN page for a description of its exact syntax and functionality.
I have records that have an index attribute to maintain their position in relation to each other.
I have a plugin that performs a renumbering operation on these records when the index is changed or new one created. There are specific rules that apply to items that are at the first and last position in the list.
If a new (or existing changed) item is inserted into the middle (not technically the middle...just somewhere between start and end) of the list a renumbering kicks off to make room for the record.
This renumbering process fires in a new execution pipeline...We are updating record D. When I tell record E to change (to make room for D) that of course fires the plugin on update message.
This renumbering is fine until we reach the end of the list where the plugin then gets into a loop with the first business rule that maintains the first and last record differently.
So I am trying to think of ways to pass a flag to the execution context spawned by the renumbering process so the recursion skips the boundary edge business rules if IsRenumbering == true.
My thoughts / ideas:
I have thought of using the Depth check > 1 but that isn't a reliable value as I can't explicitly turn it on or off....it may happen to work but that is not engineering a solid solution that is hoping nothing goes bump. Further a colleague far more knowledgeable than I said that when a workflow calls a plugin the depth value is off and can't be trusted.
All my variables are scoped at the execute level so as to avoid variable pollution at the class level....However if I had a dictionary object, tuple, something at the class level and one value would be the thread id and the other the flag value then perhaps my subsequent execution context could check if the same owning thread id had any values entered.
Any thoughts or other ideas on how to pass context information to a new pipeline would be greatly appreciated.
Per Nicknow sugestion I tried sharedvariables but they seem to be going out of scope...:
First time firing post op:
if (base.Stage == EXrmPluginStepStage.PostOperation)
{
...snip...
foreach (var item in RenumberSet)
{
Context.ParentContext.SharedVariables[recordrenumbering] = "googly";
Entity renumrec = new Entity("abcd") { Id = item.Id };
#region We either add or subtract indexes based upon sortdir
...snip...
renumrec["abc_indexfield"] = TmpIdx + 1;
break;
.....snip.....
#endregion
OrganizationService.Update(renumrec);
}
}
Now we come into Pre-Op of the recursion process kicked off by the above post-op OrganizationService.Update(renumrec); and it seems based upon this check the sharedvariable didn't carry over...???
if (!Context.SharedVariables.Contains(recordrenumbering))
{
//Trace.Trace("Null Set");
//Context.SharedVariables[recordrenumbering] = IsRenumbering;
Context.SharedVariables[recordrenumbering] = "Null Set";
}
throw invalidpluginexception reveals:
Sanity Checks:
Depth : 2
Entity: ...
Message: Update
Stage: PreOperation [20]
User: 065507fe-86df-e311-95fe-00155d050605
Initiating User: 065507fe-86df-e311-95fe-00155d050605
ContextEntityName: ....
ContextParentEntityName: ....
....
IsRenumbering: Null Set
What are you looking for is IExecutionContext.SharedVariables. Whatever you add here is available throughout the entire transaction. Since you'll have child pipelines you'll want to look at the ParentContext for the value. This can all get a little tricky, so be sure to do a lot of testing - I've run into many issues with SharedVariables and looping operations in Dynamics CRM.
Here is some sample (very untested) code to get you started.
public static bool GetIsRenumbering(IPluginExecutionContext pluginContext)
{
var keyName = "IsRenumbering";
var ctx = pluginContext;
while (ctx != null)
{
if (ctx.SharedVariables.Contains(keyName))
{
return (bool)ctx.SharedVariables[keyName];
}
else ctx = ctx.ParentContext;
}
return false;
}
public static void SetIsRenumbering(IPluginExecutionContext pluginContext)
{
var keyName = "IsRenumbering";
var ctx = pluginContext;
ctx.SharedVariables.Add(keyName, true);
}
A very simple solution: add a bit field to the entity called "DisableIndexRecalculation." When your first plugin runs, make sure to set that field to true for all of your updates. In the same plugin, check to see if "DisableIndexRecalculation" is set to true: if so, set it to null (by removing it from the TargetEntity entirely) and stop executing the plugin. If it is null, do your index recalculation.
Because you are immediately removing the field from the TargetEntity if it is true the value will never be persisted to the database so there will be no performance penalty.
Is that correct:
When I query a value before validation (or if validation failed) I have to use getSubmittedValue();. Once the value is validated, even if I query it in another validation later in the page/control I have to use .getValue(); since getSubmittedValue(); returns null after successful validation?
This xsnippet makes it easier to handle this. It allows you to just call getComponentValue("inputText1") to get either value or submittedValue.
Here's the function for reference:
function getComponentValue(id){
var field = getComponent(id);
var value = field.getSubmittedValue();
if( null == value ){
// else not yet submitted
value = field.getValue();
}
return value
}
There's a slightly easier way: if you're just expecting a simple single-value String, just call:
var compare = firstField.getValueAsString();
Otherwise, call:
var compare = com.ibm.xsp.util.FacesUtil.convertValue(facesContext, firstField);
The former calls the latter anyway, but is obviously a terser syntax. This does what you're looking for and more:
If the value hasn't yet been validated, returns the submitted value
If validation has already passed, returns the value after it's already been processed by any converters and / or content filters, so particularly in cases where you're trying to compare two field values, this should ensure that both values have been properly trimmed, etc., and is therefore less likely to return a false positive than just comparing the raw submitted values.
Found the answer here. So when you want to ensure that 2 text fields have the same value (use case: please repeat your email) and the first box already has a validation that might fail, you need to use submittedValue unless it is null, then you use the value. Code in the validation expression for the second field looks like this:
var firstField = getComponent("inputText1");
var compare = firstField.getSubmittedValue() || firstField.getValue();
compare == value;
You have to love it.