View Item Details On Sales Order Form

I am viewing the item details on sales order with the help of a client script but the problem is that after selecting an item, I will press ctrl+q and the details of one item will be shown But I don’t want to see the details of one item by selecting it, I want to see the details of all the products in my item master at once. I am attaching script below for better understanding.

Script:

frappe.ui.form.on('Sales Order', {
refresh(frm) {
    frappe.ui.keys.add_shortcut({
        shortcut: 'ctrl+q',
        action: () => { 
            const current_doc = $('.data-row.editable-row').parent().attr("data-name");
            const item_row = locals["Sales Order Item"][current_doc];
            
            if (item_row && item_row.item_code) {
                // Only proceed if an item is selected in the Sales Order
                frappe.call({
                    method: 'frappe.client.get_value',
                    args: {
                        doctype: 'Item',
                        filters: { name: item_row.item_code },
                        fieldname: ['item_code', 'item_name', 'item_group', 'stock_uom', 'description', 'last_purchase_rate']
                    },
                    callback: function(r) {
                        if (r.message) {
                            const item_details = r.message;
                            const d = new frappe.ui.Dialog({
                                title: __('Item Balance and Last Purchase Cost'),
                                width: 600  // Adjust width as needed
                            });
                            
                            // Constructing the HTML for item information with reduced top space
                            const itemInfoHtml = `
                                <div class="modal-body">
                                    <style>
                                        .item-info-table {
                                            margin-top: 5px; /* Adjust top margin */
                                        }
                                        .item-info-table th {
                                            width: 150px; /* Set width for first column */
                                            font-weight: bold;
                                        }
                                    </style>
                                    <table class="table table-bordered item-info-table">
                                        <tbody>
                                            <tr>
                                                <th>Item Code:</th>
                                                <th>Item Name:</th>
                                                <th>Item Group:</th>
                                            </tr>
                                            <tr>
                                                <td>${item_details.item_code}</td>
                                                <td>${item_details.item_name}</td>
                                                <td>${item_details.item_group}</td>
                                            </tr>
                                            <tr>
                                                <th>Description:</th>
                                                <th>Last Purchase Cost:</th>
                                            </tr>
                                            <tr>
                                                <td>${item_details.description}</td>
                                                <td>${item_details.last_purchase_rate}</td>
                                            </tr>
                                        </tbody>
                                    </table>
                                    
                                </div>`;
                             frappe.call({
                                method: 'erpnext.stock.dashboard.item_dashboard.get_data',
                                args: {
                                    item_code: item_row.item_code,
                                },
                                callback: function(r) {
                                    if (r.message && r.message.length > 0) {
                                        const tbody = $(d.body).find('tbody');
                                        r.message.forEach(element => {
                                            const tr = $(`
                                        <tr>
                                            <th>Warehouse</th>
                                            <th>Qty</th>
                                            <th>UOM</th>
                                        </tr>
                                            <tr>
                                                <td>${element.warehouse}</td>
                                                <td>${element.actual_qty}</td>
                                                <td>${item_details.stock_uom}</td>
                                            </tr>
                                            `).appendTo(tbody);
                                        });
                                    }
                                }
                            });
                            // Append item information HTML to dialog body
                            $(itemInfoHtml).appendTo(d.body);
                            
                            // Show the dialog
                            d.show();
                        }
                    }
                });
            } else {
                // Display a message or handle the case where no item is selected
                frappe.msgprint('Please select an item in the Sales Order to view details.', 'Info');
            }
        },
        page: this.page,
        description: __('Get Item INFO'),
        ignore_inputs: true
    });
}

});

Thank You

Hi @falah123,

Please apply it.

frappe.ui.form.on('Sales Order', {
    refresh(frm) {
        frappe.ui.keys.add_shortcut({
            shortcut: 'ctrl+q',
            action: () => {
                frappe.call({
                    method: 'frappe.client.get_list',
                    args: {
                        doctype: 'Item',
                        fields: ['name', 'item_code', 'item_name', 'item_group', 'stock_uom', 'description', 'last_purchase_rate']
                    },
                    callback: function(r) {
                        if (r.message && r.message.length > 0) {
                            const itemDetails = r.message;
                            const d = new frappe.ui.Dialog({
                                title: __('Item Details'),
                                size: "large",
                            });

                            let itemInfoHtml = `
                                <div class="modal-body">
                                    <table class="table table-bordered">
                                        <thead>
                                            <tr>
                                                <th>Item Code</th>
                                                <th>Item Name</th>
                                                <th>Item Group</th>
                                                <th>Stock UOM</th>
                                                <th>Description</th>
                                                <th>Last Purchase Rate</th>
                                            </tr>
                                        </thead>
                                        <tbody>`;

                            // Appending details of each item to the HTML
                            itemDetails.forEach(item => {
                                itemInfoHtml += `
                                    <tr>
                                        <td>${item.item_code}</td>
                                        <td>${item.item_name}</td>
                                        <td>${item.item_group}</td>
                                        <td>${item.stock_uom}</td>
                                        <td>${item.description}</td>
                                        <td>${item.last_purchase_rate}</td>
                                    </tr>`;
                            });

                            itemInfoHtml += `
                                        </tbody>
                                    </table>
                                </div>`;

                            $(itemInfoHtml).appendTo(d.body);

                            d.show();
                        }
                    }
                });
            },
            page: this.page,
            description: __('Get Item Details'),
            ignore_inputs: true
        });
    }
});

It gets the item from the item master.

Output:

Excellent :ok_hand: :+1:
can select the item from it and it gets added to the sales order item table.

Hi @falah123,

I knew it. Please apply it.

frappe.ui.form.on('Sales Order', {
    refresh(frm) {
        frappe.ui.keys.add_shortcut({
            shortcut: 'ctrl+q',
            action: () => {
                const items = frm.doc.items || [];
                if (items.length === 0) {
                    frappe.msgprint('Please add items to the Sales Order.', 'Info');
                    return;
                }

                const itemCodes = items.map(item => item.item_code);

                frappe.call({
                    method: 'frappe.client.get_list',
                    args: {
                        doctype: 'Item',
                        filters: { 'name': ['in', itemCodes] },
                        fields: ['name', 'item_code', 'item_name', 'item_group', 'stock_uom', 'description', 'last_purchase_rate']
                    },
                    callback: function(r) {
                        if (r.message && r.message.length > 0) {
                            const itemDetails = r.message;
                            const d = new frappe.ui.Dialog({
                                title: __('Item Details'),
                                size: "extra-large",
                            });

                            let itemInfoHtml = `
                                <div class="modal-body">
                                    <table class="table table-bordered">
                                        <thead>
                                            <tr>
                                                <th>Item Code</th>
                                                <th>Item Name</th>
                                                <th>Item Group</th>
                                                <th>Stock UOM</th>
                                                <th>Description</th>
                                                <th>Last Purchase Rate</th>
                                            </tr>
                                        </thead>
                                        <tbody>`;

                            itemDetails.forEach(item => {
                                itemInfoHtml += `
                                    <tr>
                                        <td>${item.item_code}</td>
                                        <td>${item.item_name}</td>
                                        <td>${item.item_group}</td>
                                        <td>${item.stock_uom}</td>
                                        <td>${item.description}</td>
                                        <td>${item.last_purchase_rate}</td>
                                    </tr>`;
                            });

                            itemInfoHtml += `
                                        </tbody>
                                    </table>
                                </div>`;

                            $(itemInfoHtml).appendTo(d.body);

                            d.show();
                        }
                    }
                });
            },
            page: this.page,
            description: __('Get Item Details'),
            ignore_inputs: true
        });
    }
});

Hope this helps! :wink:

Sorry, I could not explain my requirement to you. The details of all the items coming from the first script are absolutely perfect. The form opened from the first script and all the item details are being shown in it. i want to add items from it. Screen-shot below.

That for, you have to think the long logic, i think it’s tricky.

Really appreciate friend for all your assistance, blessings and cheers for you.

The static list is achieved, thats good.

But now our client is demanding that in his software, he is getting a complete list of items which can be navigated and an item can be selected,
Once a particular item is selected, further pressing f8 on that item it gives entire purchase history (entire list of details such as Purc Date, Supplier, Purchase Price, Qts etc) of that selected item and pressing f2 on that item it gives entire Sales history (entire list of details such as Sales Date, Customer, Sales Price, Qts etc) of that selected item. Pls provide some valuable clues on this, really appreciate your efforts and thanks in advance.

Many thnks again.

:roll_eyes: ohh

There is no Warehouse and balance in this code,
I tried this method =’ erpnext.stock.dashboard.item_dashboard.get_data’,
But this error is coming ‘Field not permitted in query: actual_qty’.
your code :point_down:

frappe.ui.form.on('Sales Order', {
refresh(frm) {
    frappe.ui.keys.add_shortcut({
        shortcut: 'ctrl+q',
        action: () => {
            frappe.call({
                method: 'frappe.client.get_list',
                args: {
                    doctype: 'Item',
                    fields: ['name', 'item_code', 'item_name', 'item_group', 'stock_uom', 'description', 'last_purchase_rate']
                },
                callback: function(r) {
                    if (r.message && r.message.length > 0) {
                        const itemDetails = r.message;
                        const d = new frappe.ui.Dialog({
                            title: __('Item Details'),
                            size: "large",
                        });

                        let itemInfoHtml = `
                            <div class="modal-body">
                                <table class="table table-bordered">
                                    <thead>
                                        <tr>
                                            <th>Item Code</th>
                                            <th>Item Name</th>
                                            <th>Item Group</th>
                                            <th>Stock UOM</th>
                                            <th>Description</th>
                                            <th>Last Purchase Rate</th>
                                        </tr>
                                    </thead>
                                    <tbody>`;

                        // Appending details of each item to the HTML
                        itemDetails.forEach(item => {
                            itemInfoHtml += `
                                <tr>
                                    <td>${item.item_code}</td>
                                    <td>${item.item_name}</td>
                                    <td>${item.item_group}</td>
                                    <td>${item.stock_uom}</td>
                                    <td>${item.description}</td>
                                    <td>${item.last_purchase_rate}</td>
                                </tr>`;
                        });

                        itemInfoHtml += `
                                    </tbody>
                                </table>
                            </div>`;

                        $(itemInfoHtml).appendTo(d.body);

                        d.show();
                    }
                }
            });
        },
        page: this.page,
        description: __('Get Item Details'),
        ignore_inputs: true
    });
}

});

please tell me how to achieve.

Everything is not doable on the js side. stock and warehouse for you have to get the data from the Bin doctype.

code to get warehouse and item balance qty,
code :point_down:

frappe.ui.form.on('Sales Order', {
refresh(frm) {
    frappe.ui.keys.add_shortcut({
        shortcut: 'f2',
        action: async () => {
            try {
                const itemResponse = await frappe.call({
                    method: 'frappe.client.get_list',
                    args: {
                        doctype: 'Item',
                        fields: ['name', 'item_code', 'item_name', 'item_group', 'stock_uom', 'description', 'last_purchase_rate']
                    }
                });

                if (itemResponse && itemResponse.message && itemResponse.message.length > 0) {
                    const itemDetails = itemResponse.message;
                    const d = new frappe.ui.Dialog({
                        title: __('Item Details'),
                        size: 'large'
                    });

                    let itemInfoHtml = `
                        <div class="modal-body">
                            <table class="table table-bordered">
                                <thead>
                                    <tr>
                                        <th>Item Code</th>
                                        <th>Item Name</th>
                                        <th>Item Group</th>
                                        <th>Stock UOM</th>
                                        <th>Description</th>
                                        <th>Last Purchase Rate</th>
                                        <th>Warehouse</th>
                                        <th>Stock Quantity</th>
                                    </tr>
                                </thead>
                                <tbody>`;

                    // Loop through each item
                    for (const item of itemDetails) {
                        const binResponse = await frappe.call({
                            method: 'frappe.client.get_list',
                            args: {
                                doctype: 'Bin',
                                filters: { item_code: item.item_code },
                                fields: ['warehouse', 'actual_qty']
                            }
                        });

                        let warehouseHtml = '';
                        let stockQtyHtml = '';

                        if (binResponse && binResponse.message && binResponse.message.length > 0) {
                            const binDetails = binResponse.message;
                            binDetails.forEach(bin => {
                                warehouseHtml += `${bin.warehouse}<br>`;
                                stockQtyHtml += `${bin.actual_qty}<br>`;
                            });
                        } else {
                            warehouseHtml = 'N/A';
                            stockQtyHtml = 'N/A';
                        }

                        itemInfoHtml += `
                            <tr>
                                <td>${item.item_code}</td>
                                <td>${item.item_name}</td>
                                <td>${item.item_group}</td>
                                <td>${item.stock_uom}</td>
                                <td>${item.description}</td>
                                <td>${item.last_purchase_rate}</td>
                                <td>${warehouseHtml}</td>
                                <td>${stockQtyHtml}</td>
                            </tr>`;
                    }

                    itemInfoHtml += `
                                </tbody>
                            </table>
                        </div>`;

                    $(itemInfoHtml).appendTo(d.body);
                    d.show();
                } else {
                    frappe.msgprint('No item details found.');
                }
            } catch (err) {
                console.error('Error fetching data:', err);
                frappe.msgprint('Error fetching item details. Please try again.');
            }
        },
        page: this.page,
        description: __('Get Item Details'),
        ignore_inputs: true
    });
} });

Output:

@NCP Thank You so much Brother for your help :+1:.