Need help customizing BOM

Hi Friends ,

I need to customize the BOM , only the items which pass certain condition should appear when I click the add item field in the BOM , any ideas ?

In detail : I have products with certain chemical composition , only the raw materials with the same chemical composition as that of the item_code (product) should get displayed in the bom item select field .

I mean I should filter the items based on certain condition .

Thanks in advance,

You can do this with a custom script. I can’t understand exactly what fields you want to filter, and what the filters will look like, but it should look something like this:

[If you are filtering a field in the parent]

cur_frm.fields_dict[‘bom item select field’].get_query = function(doc, cdt, cdn) {
return {
filters:{‘chemical_composition’: doc.chemical_composition}
}
}

[If you are filtering a field in a child table]

cur_frm.fields_dict[‘items’].grid.get_field(‘item_code’).get_query =
function(doc, cdt, cdn) {
return{
filters:{‘chemical_composition’: doc.chemical_composition}
}
}

Some good information on custom scripts (but doesn’t show the filtering code above):
https://github.com/frappe/frappe/wiki/Client-Side-Scripting-(new)-(wip)

1 Like

Thank you for your swift response Sir , I am able to achieve something with the below script , those items which has carbon value 12 will get displayed .But what I want is those items which has carbon value less than or equal to the item I selected in the item code should be displayed . Please help

frappe.ui.form.on("BOM", "refresh", function(frm) {
    cur_frm.set_query("item_code", function() {
        return {
            "filters": {
                "percnt_carbon_min": "12"
            }
        };
    });
});

What should I put in the place of 12 so that the entered item_code’s carbon value will be checked and those items which has equal or less carbon value of the entered items will be displayed ?

Thanks in advance

I think this should work:

frappe.ui.form.on("BOM", {
     item: function(frm) {
 		frappe.call({
       "method": "frappe.client.get_value",
       "args": {
          "doctype": "Item",
          "filters": {"item_code": cur_frm.doc.item},
          "fieldname": "percnt_carbon_min"
        }, 
 			callback: function(r) { 
 				cur_frm.set_query("item_code", "items", function(doc, cdt, cdn){
 					return {
 						"filters": {
 							"percnt_carbon_min": ["<=",r.percnt_carbon_min]
 						 }
 					}
 				});
 			}
 		});
         
     }
 });
1 Like

Thanks a lot sir , you saved my day . I will give a try and let you know . Thanks again.

Sir , this script is not working . Please help

frappe.ui.form.on("BOM", {
item: function(frm) {
frappe.call({
"method": "frappe.client.get_value",
"args": {
"doctype": "Item",
"filters": {"item_code": cur_frm.doc.item},
"fieldname": "percnt_carbon_min"
}, 
callback: function(r) { 
cur_frm.set_query("item_code", "items", function(doc, cdt, cdn){
return {
"filters": {
"percnt_carbon_min": ["<=",r.percnt_carbon_min]
}
}
});
}
});

}
});

Even tried this script , but it is not working ,

{
frappe.ui.form.on("BOM", "refresh", function(frm, doctype, name) 
	{
		cur_frm.get_field("item_code").get_query = function(doc, cdt, cdn) 
		{
			var item = frappe.get_doc(cdt, cdn);
			var c = " ";
            if (item.percnt_carbon_min) c=item.percnt_carbon_min ;
            return { filters: {'item_code': c}} 
		}
	}
);		
}

Can you explain the problem?

Where do you keep the percnt _ carbon_min fields? That script should work if the percnt_carbon_min field is a custom field for item. It should make sure that any items added to the BOM are <= the percnt_carbon_min of the item the BOM is made for.

1 Like

Sir , thanks a lot for quick response , Yes sir ,percnt_carbon_min is a custom field in item doctype .I do have this percnt_carbon_min field in item doctype above the brand field .
My concern is raw material and product both have this field percnt_carbon_min , if I select the product , only the raw materials with the same value or less than that of percnt_carbon_min should display . I copied your script and pasted it in BOM manufacturing custom script location and reloaded , cleared cache several times , but it filters nothing , please help

I even tried removing ‘’<’’ to ensure only the products with the same value of percnt_carbon_min as that of the item_code i selected will display , but it displays everything , it does not filter anything . Please help .

Sir even I tried this script , but it is not working , please help

frappe.ui.form.on("BOM", {
item: function(frm) {
frappe.call({
"method": "frappe.client.get_value",
"args": {
"doctype": "Item",
"filters": {"item_code": cur_frm.doc.item},
"fieldname": "percnt_carbon_min"
}, 
callback: function(r) { 
cur_frm.get_field("item_code").set_query = function(doc, cdt, cdn) 
		{
			var item = frappe.get_doc(cdt, cdn);
			
            if (item.percnt_carbon_min) r=item.percnt_carbon_min ;
            return { filters: {'item_code': r}} 
		}
}
}
});
}
});

}
});

Sir , I understood one thing , the items going to get filtered is in a child table , so I copied your script in both parent and child custom script location , even after that the problem persists . To overcome this i created a field in BOM with the name item_code , even that didn’t work. Perhaps the filter could have got applied but should the refresh function be added here ?

For the ease of reference and to have clarity , I have put the field names here ,

  1. BOM field name - item
  2. BOM ITEM child table going to get filtered - field name - item_code

Should the script be modified for a child table ? If so the case will be that the control field will be in the parent doc and items going to get filtered will be in child table ? Could you please guide me on this with the script ? Also can you guide me to display only the raw materials when adding BOM

Thanks in advance

Sir please help me

Sorry, I had a small bug in my code. I also added an additional filter that requires that the Item Group be a Raw Material. If you indicate that it is a Raw Material somewhere else, you’ll need to change the filter to match your requirements.

frappe.ui.form.on(“BOM”, {
item: function(frm) {
frappe.call({
“method”: “frappe.client.get_value”,
“args”: {
“doctype”: “Item”,
“filters”: {“item_code”: cur_frm.doc.item},
“fieldname”: “percnt_carbon_min”
},
callback: function® {
cur_frm.set_query(“item_code”, “items”, function(doc, cdt, cdn){
return {
“filters”: {
“percnt_carbon_min”: ["<=",r.message.percnt_carbon_min],
“item_group”: “Raw Material”
}
}
});
}
});

}
});

1 Like

Thanks a ton for the script and taking time to guide me , but the script is not working sir , I even copied the script in BOM-item child table location as well but it is not working . Sorry if I had disturbed you , sir could you please help me with the script when you are free

Thanks in advance

For the first item being added to bom , it wont work .Sir the script is working if I add one more item , How to add refresh function here ? Thanks a lot for the script. And one more issue , I went on adding my next filter , now the filter is taking the second script and it neglects the first script , also the product for which BOM is being prepared is also getting displayed in the drop down , please guide me on this

frappe.ui.form.on("BOM", {
item: function(frm) {
frappe.call({
"method": "frappe.client.get_value",
"args": {
"doctype": "Item",
"filters": {"item_code": cur_frm.doc.item},
"fieldname": "percnt_carbon_max"
}, 
callback: function(r) { 
cur_frm.set_query("item_code", "items", function(doc, cdt, cdn){
return {
"filters": {
"percnt_carbon_max": ["<=",r.message.percnt_carbon_max],
}
}
});
}
});
}
});

then I tried setting the second query in the same loop like this but it bricks the complete system , what should i do here

frappe.ui.form.on("BOM", {
item: function(frm) {
frappe.call({
"method": "frappe.client.get_value",
"args": {
"doctype": "Item",
"filters": {"item_code": cur_frm.doc.item},
"fieldname": "percnt_carbon_min","percnt_carbon_max"
}, 
callback: function(r) { 
cur_frm.set_query("item_code", "items", function(doc, cdt, cdn){
return {
"filters": {
"percnt_carbon_min": [">=",r.message.percnt_carbon_min],
"percnt_carbon_max": ["<=",r.message.percnt_carbon_max],
"item_group": "Raw Material"
}
}
});
}
});

}
});

My concerns in detail .

  • The item for which we are preparing the BOM is also getting displayed in the drop down.
  • The script is working if I add one more item , for the first item being added to bom , it wont work . How to add refresh function here
  • I am not able to add more filters , if I add the second filter it neglects the first filter.

Many thanks for your continued support . Please guide me on this when you find sometime.

Thanks in advance

I’m not sure why it is not working on the first attempt for you. Is there already an empty child created in the table when you create the form or is it completely empty?

The filters you are showing are almost mutually exclusive.

This is the same thing as "percnt_carbon_max": ["=",r.message.percnt_carbon_max]

If the system is “bricking”, you should check the console log for your browser. In chrome, press Ctrl-Shift-I. Report what you are seeing in the console here so we can debug it.

Finally, you only need one script for all the filters. Add them in the same section as the first filter:

frappe.ui.form.on(“BOM”, {
item: function(frm) {
frappe.call({
“method”: “frappe.client.get_value”,
“args”: {
“doctype”: “Item”,
“filters”: {“item_code”: cur_frm.doc.item},
“fieldname”: [“percnt_carbon_min”, “item_code”]
},
callback: function® {
cur_frm.set_query(“item_code”, “items”, function(doc, cdt, cdn){
return {
“filters”: {
“percnt_carbon_min”: ["<=",r.message.percnt_carbon_min],
“item_group”: “Raw Material”,
“item_code”: ["!=", r.message.item_code],
}
}
});
}
});

}
});

1 Like

Sir thanks a ton for replying , an empty child is already created when I open the BOM , it is not completely empty . I do have around 24 filters to be applied , percnt_carbon_min , percnt_man_min, percnt_carbon_max , percnt_man_max, and so on , So i tried to add the second filter , this is my script

frappe.ui.form.on("BOM", {
item: function(frm) {
frappe.call({
"method": "frappe.client.get_value",
"args": {
"doctype": "Item",
"filters": {"item_code": cur_frm.doc.item},
"fieldname": "percnt_carbon_min","percnt_carbon_max"
}, 
callback: function(r) { 
cur_frm.set_query("item_code", "items", function(doc, cdt, cdn){
return {
"filters": {
"percnt_carbon_min": [">=",r.message.percnt_carbon_min],
"percnt_carbon_max": ["<=",r.message.percnt_carbon_max],
"item_group": "Raw Material"
}
}
});
}
});

}
});

And this is the error i get in the console after applying this script ,

VM268:266 Uncaught SyntaxError: Unexpected token }setup @ form.min.js:2510_f.Frm.setup @ form.min.js:213_f.Frm.refresh @ form.min.js:528load @ form.min.js:97(anonymous function) @ form.min.js:82callback @ desk.min.js:5784callback @ desk.min.js:1194200 @ desk.min.js:1219(anonymous function) @ desk.min.js:1306j @ jquery.min.js:2fireWith @ jquery.min.js:2x @ jquery.min.js:4(anonymous function) @ jquery.min.js:4
form.min.js:4615 Uncaught TypeError: Cannot read property 'refresh' of undefined

Also the item for which we are preparing the BOM is even getting displayed in the drop down .Thanks again for spending time to solve my issue .

It looks like you have too many brackets: }. To get more information about the error, you should be able to click a link on VM268:266 which will take you to the code surrounding the error. That will show you what code is causing the error. Paste it here if you need help figuring it out.

Also, I think you need square brackets around the fieldnames: "fieldname": ["percnt_carbon_min","percnt_carbon_max"].

1 Like

Sir thank you so much , the script now works like a charm , but does not work for the first instance , only the second row is getting filtered , is there any way to add refresh function here ? Thanks a lot for this awesome script .

I think this is a bug… Not sure how to fix this.

1 Like