I am fairly new to Drools and getting my head around it.
Scenario:
rule A output -> should trigger Rule b , Rule c and send then get the final output etc
Example : For simplification
CountryBean --> { String isdCode ,List<String> tates}
rule "Get States by Country's ISD Code"
no-loop true
when country: Country(isCode=="+1")
then
country.setStates("Kentucky" , "North Carolina"....);
update(country);
StateBean --> {String state,String population}
rule "Get Population of States"
no-loop true
when state: States(state !="", $state=state)
then
if(state=="Kentucky")
state.population("1M");
update(state)
My Solution
Execute the first Rule
then iterate over the states and execute States rules
Country country = new Country("+1");
ksession.insert(country )
ksession.fireAllRules();
List<States> stateList=new ArrayList<States>();
country.getStates().forEach(state-> {
ksession.insert(new State(state));
ksession.fireAllRules();stateList.add(state);
});
I dont think this is the right way to do it. How should I approach this problem ?
Related
I'm creating a chat app where data are stored like the image given below.
I want to add a validation rule for "Text" to be less than 300 characters long. I used the validation rule:
"TextChannels":{
"Anime_Weebs":{
".validate": "newData.child('Text').val().length < 200"
},
But this rule is not working. Instead any type of text is getting rejected.
This is my database:
And this is my Flutter AddMessage code:
_addMessage() {
final user = FirebaseAuth.instance.currentUser;
final time = DateTime.now().toUtc().millisecondsSinceEpoch;
_dbRef
.ref('TextChannels/${channelName}/Messages/')
.child('${time.toString()}${user!.uid}')
.set({
'Author': user.displayName,
'Author_ID': user.uid,
'Author_Username': username,
'Time': time,
'Text': _message,
'Delivered': false,
'Day': days
});
}
This rule that you have:
"TextChannels":{
"Anime_Weebs":{
".validate": "newData.child('Text').val().length < 200"
},
This rule says that your database has a path TextChannels/Anime_Weebs that has a child node Text whose length you want to restrict. But if we look at your database, there is no path TextChannels/Anime_Weebs/Text - and since a non-existing value is definitely not longer than 200 characters, the rule doesn't block any write operation.
If you want to apply a rule to all child nodes under a path, you need to use a wildcard variable to capture the unknown part of the path:
"TextChannels":{
"Anime_Weebs":{
"Messages": {
"$messageId": {
".validate": "newData.child('Text').val().length < 200"
}
}
},
So here the Messages and $messageId rules are new compared to your rules, and the latter indicates the the .validate rule should be applied to each child node of TextChannels/Anime_Weebs/Messages.
Currently I'm writing an example script to get the hang of the suiteScript environment and get a better idea of how it all works. Right now I've written a script that looks like it should create and save a new customer record upon deployment. I dont run into any errors loading the script into NetSuite and I put the code through a debugger and the syntax seems right.
'''
/**
* #NApiVersion 2.x
* #NScriptType ClientScript
*/
define(["N/record"], function (r) {
function creatCustomer() {
var customer = record.create({
type: record.Type.CUSTOMER,
isDynamic: false,
defaultValues: null
});
customer.setValue(
{fieldId: "firstname", value: "James", ignoreFieldChange: false},
{fieldId: "lastname", value: "Halpert"},
{fieldId: "subsidiary",value: "Training 7"},
{fieldId: "email", value: "JHalpert#DM.com"},
{fieldId: "company Name",value: "Dunder Mifflin Test"}
);
customer.save({
enableSourcing: true,
ignoreMandatoryFields: false
});
}
return {
saveRecord: creatCustomer
};
});
'''
I think the problem might be deployment, but I don't know exactly what it could be. The script gets deployed but I can't find the customer record anywhere.
You should use the Netsuite help to read about script types and script type entry points. In particular client scripts are not generally used the way you have set that up.
This question has almost nothing in it regarding script deployment issues. (I'd expect to see at least one screen shot of the deployment screen)
For what you have written each time one of the deployment target records is saved a new customer record save will be attempted.
However the script you posted will error because:
the subsidiary value should be the internalid of the subsidiary - not the subsidiary name.
you are declaring 'N/record' as function(r) but then using it like record.create
record.setValue doesn't take a list of fieldId/value pairs
It may error if the user submitting the record doesn't have permissions to create customers.
It will likely error the second time it runs because a non-unique user name is being given. (Though this depends on how your account is configured)
One way to 'play' with scripts is to open a console window on any record in edit mode (and for some other screens) and you can run individual scripts like:
require(["N/record"], function (record) {
var customer = record.create({
type: record.Type.CUSTOMER,
isDynamic: false,
defaultValues: null
});
customer.setValue({fieldId: "firstname", value: "James"}); //, ignoreFieldChange: false}, <- this is for dynamic mode and client scripts
customer.setValue({fieldId: "lastname", value: "Halpert"});
customer.setValue({fieldId: "subsidiary",value: "Training 7"});
customer.setValue({fieldId: "email", value: "JHalpert#DM.com"});
customer.setValue({fieldId: "company Name",value: "Dunder Mifflin Test"});
var custId = customer.save({
enableSourcing: true,
ignoreMandatoryFields: false
});
console.log('created customer ', custId);
});
I have the following rule
rule One
when
vg1 : Vgdoc(code() in ("IA1003", "IA1004"), colour == "red")
then
.. do something with vg1
end
when I use the vg1 in the then clause I see that it represents one object but what if both ("IA1003", "IA1004") exists? does drools only send the first one or both? and if it sends both how can I check it.
Is it possible to do something like this to
vglist : List() from collect (Vgdok(code() in ("IA1003", "IA1004")))
will this list contain both fact if they exists in the memory?
cheers
es
Your rule will hit for each item in working memory that matches.
Simplifying things, let's say that your model looks like this:
class Vgdoc {
public String getCode() { ... }
public String getColour() { ... }
}
And your rule is like what you have, syntax corrected:
rule "One"
when
vg1: Vgdoc( code in ("IA1003", "IA1004"),
colour == "red" )
then
Systen.out.println("Rule 1 fired");
end
And you have objects in working memory:
Vgdoc{ code: "IA1003", colour: "red" } // A
Vgdoc{ code: "IA1004", colour: "red" } // B
Vgdoc{ code: "IA1005", colour: "red" } // C
Vgdoc{ code: "IA1003", colour: "blue" } // D
Then your rule will fire twice, once for the item I commented as "A" and once for the item I commented as "B". (Eg. there will be two instances of Rule 1 fired printed.) It will not fire for item commented "C" because the code does not match, and it will not fire for item commented "D" because the colour field does not match.
Now, if you want to only fire once and to do something with the collection of all Vgdoc matching the condition (color 'red' and code 'IA1003' or 'IA1004'), then yes you'd use a collect. Something like this:
rule "IA1003 and IA1004 with red"
when
vgList: List() from collect( Vgdoc( code in ("IA1003", "IA1004"), colour == "red" ))
then
System.out.println("Rule fired, match count: " + vgList.size());
// vgList will contain all items that match the conditions for code and colour
end
This version of the rule, with the same inputs from before, will fire exactly once and will print: Rule fired, match count: 2.
Which one you choose to use depends on your use case.
I have been trying to develop an app that takes an order on Shopify on a different channel. I successfully placed an order through the API but I am not able to include the discount code along with the order. The JSON object for the POST data is as below:
{
order: {
email : request.params.order.email, // string
financial_status : 'pending', // string
send_receipt : true, // boolean
send_fulfillment_receipt : false, // boolean
note : request.params.order.note, // string
discount_codes : [], // supposed to be an array of Object| Problem here,
line_items : request.params.order.line_items, // array
customer : request.params.customer, // JSON object
billing_address : request.params.order.billing_address, // JSON object
shipping_address : request.params.order.shipping_address // JSON object
}
}
According to the documentation, the discount_codes is like this -
Applicable discount codes that can be applied to the order. If no codes exist the value will default to blank. A Discount code will include the following fields:
amount: The amount of the discount.
code: The discount code.
type: The type of discount. Can be one of : "percentage", "shipping", "fixed_amount" (default).
What am I doing wrong? My discount_codes is this
[{amount: 100,code:'WELCOME10',type:'percentage'}]
Has anyone done this before?
According to this response from Shopify what you are trying to do is only possible if you pass the total_discounts field along as well with the total amount of the discount you want to apply.
As you will see in this other answer, any codes you have created through Shopify are not available to use with the API and their usage will not be recorded.
I was trying to use this API in order to test the application of different coupon codes that I was generating, but this does not seem to be possible. Apparently, the API was intended for applying discounts that are custom, not ones that already exist in Shopify. This is a frustrating limitation to me.
I successfully create orders with discounts all the time, without ShopifyPlus as that is irrelevant. The data structure that works for me looks like this:
[ { "code": "Shop By PizzleFuzzle 10%", amount: "10", "type": "percentage" } ]
The discount object is available only for Shopify Plus merchants.
Once you are a Shopify Plus merchant, you will be able to create discount codes like that:
POST /admin/discounts.json
{
"discount": {
"discount_type": "percentage",
"value": "15.0",
"code": "balderdash"
}
}
Please see more detailed documentation in the discount object at Shopify API: https://help.shopify.com/api/reference/discount
You should use the value property name instead of amount property name.
e.g.
{value: 100,code:'WELCOME10',type:'percentage'}
and not
{amount: 100,code:'WELCOME10',type:'percentage'}
I am attempting to create a workflow rule but am running into syntax errors. I would like the workflow to fire if the record type is equal to "Athlete", "Coach", or "Judge", the Profile Status is equal to "Active", and the Medical Exam Date is equal to today. This is what I have so far:
IF
(AND(RecordType.Name == 'Athlete',Profile_r.Status_c == 'Active') , TODAY() = Medical_Exame_Date)
Thanks
There are few cases where you would need to use an IF(condition, iftrue, iffalse) in a workflow. When the workflow is evaluated, it's just looking for the entire condition to return true or false. I think this may be what you're looking for:
AND(
OR(
RecordType.Name == 'Athlete',
RecordType.Name == 'Coach',
RecordType.Name == 'Judge'
),
Profile__r.Status__c == 'Active',
Medical_Exame_Date__c == TODAY()
)