Explode Product bundle in Sales Order or Sales Invoice

Is there a way to explode the product bundle into individual items on adding to sales order or sales invoice?

Use Case: Some times one or more items as part of the bundle may not be available, so a different items will be sent. If the bundle is automatically exploded, these unavailable items can be replaced with different items.

You have to write a custom client script for this.
You can call this function on a button click in refresh function.

var get_items_from_product_bundle = function(frm) {
	var me = this;
	var dialog = new frappe.ui.Dialog({
		title: __("Get Items from Product Bundle"),
		fields:[
			{ fieldtype: 'Link', options: 'Product Bundle', label: 'Product Bundle', fieldname: "product_bundle", reqd: true,
				description:'All items in the product bundle selected will be added to the Sales Invoice items.'
			}
		]
	});
	
    dialog.set_primary_action(__('Add'), function() {
        var bundle_price_list_rate = 0;
        var selected_bundle = {};
        var product_bundle = dialog.fields_dict.product_bundle.input.value;
        
        if (product_bundle) {
            frm.set_value("items", []);
            frappe.call({
                method: "frappe.client.get",
                args: {
                    doctype: "Product Bundle",
                    name: product_bundle,
                },
                callback(r) {
                    if(r.message) {
                        selected_bundle = r.message;
                        for(let i=0; i<selected_bundle.items.length; i++){
                            var si_item = frappe.model.add_child(frm.doc, 'Sales Invoice Item', 'items');
                            frappe.model.set_value(si_item.doctype, si_item.name, 'item_code', selected_bundle.items[i].item_code);
                            frappe.model.set_value(si_item.doctype, si_item.name, 'qty', selected_bundle.items[i].qty);
                            if(selected_bundle.items[i].qty > 1){
                                frappe.model.set_value(si_item.doctype, si_item.name, 'qty', parseFloat(selected_bundle.items[i].qty));
                            }
                        }
                        frm.refresh_fields();
                        dialog.hide();
                    }
                }
            });
        } else {
            frappe.msgprint(__("Please select Product Bundle"));
        }
        
    });
	
	dialog.show();
};
1 Like

As alternative, it is also possible to do something similar whenever a new item is added. If it is a PB, the childs are added to the item list.

frappe.ui.form.on("Sales Order Item", "item_code", function(frm, cdt, cdn) {
    var d = locals[cdt][cdn];

    if (d.item_code) {
        frappe.db.get_list("Product Bundle Item", {
            filters: {
                parent: d.item_code
            },

            fields: ['item_code', 'qty', 'description']
        }).then((data) => {
            frappe.run_serially([
                () => {
                    if (data.length > 0) {
                        $.each(data, function(i, f) {
                            var row = frappe.model.add_child(cur_frm.doc, "Sales Order Item", "items");
                            row.item_code = f.item_code;
                            row.delivery_date = cur_frm.doc.delivery_date;
                            row.item_name = f.item_code;
                            row.description = f.description;
                            row.qty = f.qty;
                        })
                        refresh_field("items");
                    }
                }
            ]);
        });
    }
});
2 Likes

Thank You. Should be the right approach. Let me validate this.

Hello Dear ,
Could you guide me For Creating Purchase order from sales order of Bundle Product
I am using version 14.13 ,
But there is one Issue here

  1. As Bundle Product Which suppose be Be NON Stock and NON Purchase item ,
  2. When Clicking Create purchase order in List Loading Bundle Product where it suppose to Load Bundled Items , so that after selecting Supplied for each item Supplier PO could be created ,